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:
Linux (ubuntu on WSL using docker) | Timer is accurate within 1 nanoseconds:
Linux (ubuntu running the exe):
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
NOTE: As requested, here is a github link with the code and docker files
https://github.com/anthonyMc11/TaskProblem/tree/main
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With