È necessario un ritardo di microsecondi nell'app .NET per limitare la velocità di trasmissione multicast UDP

StackOverflow https://stackoverflow.com/questions/1631501

Domanda

Sto scrivendo una coppia client / server multicast UDP in C # e ho bisogno di un ritardo dell'ordine di 50-100 µsec (microsecondi) per limitare la velocità di trasmissione del server. Questo aiuta ad evitare una significativa perdita di pacchetti e aiuta anche a evitare di sovraccaricare i client che sono associati all'I / O del disco. Si prega di non suggerire Thread.Sleep o Thread.SpinWait. Non vorrei chiedere se ne avessi bisogno.

Il mio primo pensiero è stato quello di utilizzare una sorta di contatore ad alte prestazioni e di fare un semplice ciclo while () controllando il tempo trascorso, ma mi piacerebbe evitarlo in quanto sembra complicato. Ciò non comprometterebbe anche l'utilizzo della CPU per il processo del server?

Punti bonus per una soluzione multipiattaforma, ovvero non specifica per Windows. Grazie in anticipo, ragazzi!

È stato utile?

Soluzione

Vorrei usare cronometro ma avrei bisogno di un ciclo

leggi questo per aggiungere più estensioni al cronometro, come ElapsedMicroseconds

o qualcosa del genere potrebbe funzionare anche

System.Diagnostics.Stopwatch.IsHighResolution DEVE essere vero

    static void Main(string[] args)
    {
        Stopwatch sw;
        sw = Stopwatch.StartNew();
        int i = 0;

        while (sw.ElapsedMilliseconds <= 5000)
        {
            if (sw.Elapsed.Ticks % 100 == 0)
            { i++; /* do something*/ }
        }
        sw.Stop();


    }

Altri suggerimenti

I tempi di sospensione molto brevi sono generalmente raggiunti meglio da uno spin loop della CPU (come il tipo che descrivi). In genere si desidera evitare di utilizzare le chiamate con timer ad alta precisione in quanto possono esse stesse occupare tempo e distorcere i risultati. Non mi preoccuperei troppo del pegging della CPU sul server per tempi di attesa così brevi.

Incapsulerei il comportamento in una classe, come segue:

  • Crea una classe il cui costruttore statico esegue un loop spin per diversi milioni di iterazioni e acquisisce il tempo impiegato. Questo ti dà un'idea di quanto tempo impiegherebbe un ciclo a ciclo singolo sull'hardware sottostante.
  • Calcola un valore US / iterazione che puoi utilizzare per calcolare i tempi di sonno arbitrari.
  • Quando ti viene chiesto di dormire per un determinato periodo di tempo, dividi gli utenti in modalità sleep per il valore US / iteration precedentemente calcolato per identificare il numero di iterazioni in loop da eseguire.
  • Gira usando un ciclo while fino allo scadere del tempo stimato.

Ho riscontrato questo requisito quando avevo bisogno di maggiore precisione con la mia applicazione multicast.

Ho scoperto che la soluzione migliore risiede con i timer MultiMedia, come visto in questo esempio .

Ho usato questa implementazione e ho aggiunto l'invocazione asincrona di TPL. Dovresti vedere il mio progetto SimpleMulticastAnalyzer per ulteriori informazioni.

    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);
        }
    }

Hai guardato timer multimediali ? Probabilmente potresti trovare una libreria .NET da qualche parte che avvolge le chiamate API da qualche parte.

Scoraggerei l'uso di spin loop in quanto consuma e crea thread di blocco. thread.sleep è meglio, non utilizza le risorse del processore durante la sospensione, ma riduce il tempo. Provalo e vedrai dal task manager come il picco dell'utilizzo della CPU con lo spin loop.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top