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. P>
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? P>
Points de bonus pour une solution multi-plate-forme, c'est-à-dire que non spécifique Windows. Merci d'avance, les gars! P>
6 Réponses :
J'utiliserais chronomètre mais aurait besoin d'un boucle
+1, devrait être un moyen beaucoup plus précis de mesurer de minuscules intervalles en tenant compte de la commutation des tâches et des effets similaires, par rapport au calcul du décompte d'une boucle à partir d'une mesure d'échantillon.
... Maintenant, vous supposez que vous obtenez un compte de coche qui est exactement divisible de 100.
@Freed, la proprementie "écoulée" est un objet Timespan qu'un tique signifie 100 nanosecondes
Que se passe-t-il si vous obtenez un délai de plus de 200 nanosecondes, juste lorsque les tiques sont à 99? Cela ne voudrait-il pas vous causer / non / pas / piège que quelques-uns plus tard de 100 ticks?
@Andrew Matthews, ce fut un exemple très simple sur la manière dont cela pourrait être mis en œuvre, je ne m'attendais pas à une copie brute / pâte de ce code.
Que ferais-tu différemment?
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. P>
Je encapsulerais le comportement dans une classe, comme suit: P>
Avez-vous regardé TIMERS MULTIMÉDIA ? Vous pouvez probablement trouver une bibliothèque .NET quelque part qui enveloppe les appels API quelque part. P>
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. P>
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 code> appels avec un
chronomètre code> 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.
J'ai connu avec une telle exigence lorsque j'avais besoin de plus de précision avec ma demande de multidiffusion. P>
J'ai constaté que la meilleure solution réside avec les minuteries multimédia, comme indiqué dans cet exemple . p>
J'ai utilisé cette implémentation et ajouté TPL Async l'invoquera. Vous devriez voir mon SimpleMulticastanalyzer projet pour plus d'informations. P>
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); } }