Need microsecond delay in .NET app for throttling UDP multicast transmission rate

12,180

Solution 1

I would use stopwatch but would need a loop

read this to add more extension to the stopwatch, like ElapsedMicroseconds

or something like this might work too

System.Diagnostics.Stopwatch.IsHighResolution MUST be true

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


    }

Solution 2

Very short sleep times are generally best achieved by a CPU spin loop (like the kind you describe). You generally want to avoid using the high-precision timer calls as they can themselves take up time and skew the results. I wouldn't worry too much about CPU pegging on the server for such short wait times.

I would encapsulate the behavior in a class, as follows:

  • Create a class whose static constructor runs a spin loop for several million iterations and captures how long it takes. This gives you an idea of how long a single loop cycle would take on the underlying hardware.
  • Compute a uS/iteration value that you can use to compute arbitrary sleep times.
  • When asked to sleep for a particular period of time, divide uS to sleep by the uS/iteration value previously computed to identify how many loop iterations to perform.
  • Spin using a while loop until the estimated time elapses.

Solution 3

I've experienced with such requirement when I needed more precision with my multicast application.

I've found that the best solution resides with the MultiMedia timers as seen in this example.

I've used this implementation and added TPL async invoke to it. You should see my SimpleMulticastAnalyzer project for more information.

Solution 4

    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);
        }
    }
Share:
12,180
James Dunne
Author by

James Dunne

Senior Software Engineer

Updated on June 15, 2022

Comments

  • James Dunne
    James Dunne almost 2 years

    I'm writing a UDP multicast client/server pair in C# and I need a delay on the order of 50-100 µsec (microseconds) to throttle the server transmission rate. This helps to avoid significant packet loss and also helps to keep from overloading the clients that are disk I/O bound. Please do not suggest Thread.Sleep or Thread.SpinWait. I would not ask if I needed either of those.

    My first thought was to use some kind of a high-performance counter and do a simple while() loop checking the elapsed time but I'd like to avoid that as it feels kludgey. Wouldn't that also peg the CPU utilization for the server process?

    Bonus points for a cross-platform solution, i.e. not Windows specific. Thanks in advance, guys!

  • SoftMemes
    SoftMemes over 14 years
    +1, should be a much more accurate way of measuring tiny intervals taking into account task switching and similar effects, compared to just calculating a loop count from a sample measurement.
  • SoftMemes
    SoftMemes over 14 years
    ... now you're assuming you get a Tick count that is exactly dividable by 100.
  • mrnakumar
    mrnakumar over 14 years
    @Freed, the propriety "elapsed" is a timespan object which a tick mean 100 nanoseconds
  • Andrew Matthews
    Andrew Matthews over 13 years
    what happens if you get a 200+ nanosecond delay just when Ticks is at 99? wouldn't that cause you to /not/ trap till some later multiple of 100 ticks?
  • mrnakumar
    mrnakumar over 13 years
    @Andrew Matthews, this was a really simple example about how it could be implemented, I would not expect a raw copy/paste of this code.
  • Andrew Matthews
    Andrew Matthews over 13 years
    What would you do differently?
  • James Dunne
    James Dunne about 11 years
    I strongly suggest you research how process time-slicing works in non-realtime OSes. You will not be able to get to the microsecond precision timing level with millisecond-level sleep delays (off by a factor of 1000x), especially not when the millisecond level of precision is not guaranteed to be delivered for Thread.Sleep. Try a few Thread.Sleep calls with a Stopwatch and measure how accurate they are.
  • jun estevez
    jun estevez about 11 years
    Sorry about that, I never read the question's concern was in micro seconds, just concern on the performance issue I have read on spinwait solution.