skip to Main Content

I am struggling with a timing issue I have in Docker

Here is my test code:

    using System.Diagnostics;


    DisplayStopWatchResolution();

    var timer = new Stopwatch();
    //begin the test
    while (true)
    {
        timer.Restart();
        timer.Start();
        //Thread.Sleep(1);
        await Task.Delay(1).ConfigureAwait(false);
        timer.Stop();
        Console.WriteLine($"Task time {timer.Elapsed.TotalMilliseconds}");
    }

    static void DisplayStopWatchResolution()
    {
        if (Stopwatch.IsHighResolution)
        {
            Console.WriteLine("Operations timed using the system's high-resolution performance counter.");
        }
        else
        {
            Console.WriteLine("Operations timed using the DateTime class.");
        }

        long frequency = Stopwatch.Frequency;
        Console.WriteLine("  Timer frequency in ticks per second = {0}",
            frequency);
        long nanosecPerTick = (1000L * 1000L * 1000L) / frequency;
        Console.WriteLine("  Timer is accurate within {0} nanoseconds",
            nanosecPerTick);
    }

What I want is for the system to wait around 1ms.

However I am getting these results:

  • Windows | Timer is accurate within 100 nanoseconds:

    • await Task.Delay(1).ConfigureAwait(false); is roughly 1.942 ms (acceptable)
    • Thread.Sleep(1) is again roughly 1.942ms (acceptable)
  • Linux (ubuntu on WSL using docker) | Timer is accurate within 1 nanoseconds:

    • await Task.Delay(1).ConfigureAwait(false) is roughly 10 ms (my bad case)
    • Thread.Sleep() is 1.0712ms (really good)
  • Linux (ubuntu running the exe):

    • await Task.Delay(1).ConfigureAwait(false); is roughly 1.942 ms (acceptable)
    • Thread.Sleep(1) is again roughly 1.942ms (acceptable)

I need to use docker and would prefer to use Task.Delay() as to not block the thread however with the performance being 10x what is should b, it’s not really an option.

My question is how to fix Task.Delay() under Docker linux to not be so slow.

Thank you

2

Answers


  1. This is not the intended use case for Task.Delay(). There is no guarantee that the awaitable will return control to the task immediately once the delay has elapsed. That’s not how cooperative concurrency works (ie. asynchronous). It depends entirely on what other tasks are running and how frequently they cede control of the event loop. Task.Delay() is for retying a bit of code, but backing off a bit so as not to overload the resource you are trying to use (like an HTTP server). It is not for fine-grained time synchronisation.

    If you want to give other tasks a chance to execute before continuing in a busy loop then use await Task.Yield(). This will allow other tasks to execute (if they exist and are ready to execute), otherwise control is returned to the task immediately.

    Login or Signup to reply.
  2. It is unclear why you want to wait for 1 ms. Without that information it is hard to suggest how to make system wait so short time.

    As you have noted Thread.Sleep and Task.Delay respond differently. As mentioned in Microsoft documentation Thread.Sleep suspends running thread for given time. That means that same thread is activated after wait time and it will not respond to any calls while suspended. Task.Delay delays the task but you can call it while the delay is in effect. When delay finishes code continues running but probably in another thread because context is a task not a thread.

    The difference is that you can introduce cancellation token for Task.Delay. It is useful if wait time is long and you want to abort waiting like when waiting external device that doesn’t respond for a while.

    Is the question: How can I set up accurate timer?

    I know Windows OS sets restrictions how accurate and fast a timer can be.
    There are few options to choose from depending on your needs. But it seems like Windows OS typically caps to ~15 ms speed. HighPrecisionTimer tries to deal with that problem.

    Here are few possible solutions depending on what kind of problem you are trying to solve.

    I hope you’ll find answer from these information paths. But as I said earlier, it is unclear why do you want to have 1 ms delay.

    Is it because external device, UI event, accuracy in some other logic or what. Why would also narrow down what libraries could be recommended to achieve that short delay.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search