7
votes

Besoin de délai de microsecond dans l'application .NET pour l'étranglement Taux de transmission multidiffusion UDP

J'écris une paire de client / serveur multicast UDP dans C # et j'ai besoin d'un délai de l'ordre de 50-100 μSec (microsecondes) pour accélérer le taux de transmission du serveur. Cela aide à éviter une perte de paquets significative et contribue également à empêcher de surcharger les clients du disque I / O lié. S'il vous plaît ne suggérez pas thread.sleep ou thread.spinwait. Je ne demanderais pas si j'avais besoin de l'une de ces personnes.

Ma première pensée était d'utiliser une sorte de comptoir hautes performances et de faire une boucle simple () en vérifiant le temps écoulé, mais j'aimerais éviter cela comme il se sent krudgey. Cela n'a-t-il pas également pénétré sur l'utilisation de la CPU pour le processus de serveur?

Points de bonus pour une solution multi-plate-forme, c'est-à-dire que non spécifique Windows. Merci d'avance, les gars!


0 commentaires

6 Réponses :



9
votes

Les temps de sommeil très courts sont généralement mieux réalisés par une boucle de spin CPU (comme le genre que vous décrivez). Vous souhaitez généralement éviter d'utiliser les appels de minuterie de haute précision car ils peuvent eux-mêmes prendre du temps et incliner les résultats. Je ne m'inquiéterais pas trop sur le processeur de la CPU sur le serveur pour de tels temps d'attente courts.

Je encapsulerais le comportement dans une classe, comme suit:

  • Créez une classe dont le constructeur statique exécute une boucle d'essorage pendant plusieurs millions d'itérations et capture combien de temps il faut. Cela vous donne une idée de combien de temps un cycle de boucle unique prendrait sur le matériel sous-jacent.
  • Compute une valeur US / Itération que vous pouvez utiliser pour calculer des temps de sommeil arbitraires.
  • Lorsqu'on lui a demandé de dormir pendant une période donnée, divisez-nous au sommeil par la valeur américaine / itération précédemment calculée pour identifier le nombre d'itérations de boucle à effectuer.
  • tourner à l'aide d'une boucle tandis que le temps estimé est écoulé.

0 commentaires

0
votes

Avez-vous regardé TIMERS MULTIMÉDIA ? Vous pouvez probablement trouver une bibliothèque .NET quelque part qui enveloppe les appels API quelque part.


0 commentaires

0
votes

Je découragerais à l'aide de la boucle de spin car elle consomme et crée un fil de blocage. Thread.sleep est meilleur, il n'utilise pas la ressource de processeur pendant le sommeil, il suffit de trancher le temps. Essayez-le et vous verrez du gestionnaire de tâches à quel point l'utilisation du processeur avec la boucle de spin.


2 commentaires

Je vous suggère fortement de rechercher la manière dont les travaux de tranchage de processus dans des OSES non en temps réel. Vous ne pourrez pas accéder au niveau de synchronisation de précision microsecond avec des délais de sommeil de niveau milliseconde (désactivé par un facteur de 1000X), en particulier pas lorsque le niveau de précision millisecond n'est pas garanti pour être livré pour thread.sleep < / code>. Essayez quelques thread.sleep appels avec un chronomètre et mesurez à quel point ils sont précises.


Désolé, je ne lis jamais la préoccupation de la question était en micro secondes, ce qui concerne simplement la question de la performance que j'ai lue la solution Spinwait.



1
votes

J'ai connu avec une telle exigence lorsque j'avais besoin de plus de précision avec ma demande de multidiffusion.

J'ai constaté que la meilleure solution réside avec les minuteries multimédia, comme indiqué dans cet exemple .

J'ai utilisé cette implémentation et ajouté TPL Async l'invoquera. Vous devriez voir mon SimpleMulticastanalyzer projet pour plus d'informations.


0 commentaires

1
votes
    static void udelay(long us)
    {
        var sw = System.Diagnostics.Stopwatch.StartNew();
        long v = (us * System.Diagnostics.Stopwatch.Frequency )/ 1000000;
        while (sw.ElapsedTicks < v)
        {
        }
    }
    static void Main(string[] args)
    {
        for (int i = 0; i < 100; i++)
        {
            Console.WriteLine("" + i + " " + DateTime.Now.Second + "." + DateTime.Now.Millisecond);
            udelay(1000000);
        }
    }

0 commentaires