2

I am looking for any timer's design, which can schedule tasks with the period less than 1 millisecond. The most optimal scenario: load 25% of 1 core, when 1 separate thread is used for running this pattern.

1 millisecond is the limit for all the timers, which I know:

  • System.Windows.Forms.Timer
  • System.Timers.Timer
  • System.Threading.Timer

I have already implemented timer, which runs task every X microseconds. But it is still loading almost one core, when 1 separate thread is used for running this pattern.

The code:

private readonly TimeSpan _period;

private readonly Stopwatch _stopwatch;

private TimeSpan _lastElapsedTime;

private Double _iterationsPerPeriod;

void Run() 
{
    TimeSpan elapsed = _stopwatch.Elapsed;
    TimeSpan interval = elapsed - _lastElapsedTime;
    if (interval < _period)
    {
        Int32 iterationsToWait = (Int32) (_iterationsPerPeriod * (interval.TotalMilliseconds / _period.TotalMilliseconds));
        Thread.SpinWait(iterationsToWait);
    }

    _lastElapsedTime = _stopwatch.Elapsed;
    // RunTask();
}

void RunTimer() 
{
    while(true)
    {
        Run();
    }
}

How can I run a method every X microseconds without CPU loading?

  • you can use the Task Parallel library. see https://msdn.microsoft.com/en-us/library/dd537609(v=vs.110).aspx........ But you need to use .Net 4.0 or above – Suresh Kumar Veluswamy Feb 09 '17 at 10:01
  • Not sure you can. Windows can't switch-out your thread at that speed, so your thread will be still running and consuming CPU time. – xanatos Feb 09 '17 at 10:02
  • @SureshKumarVeluswamy, thanks. It seems to be an alternative. Using TPL will cause to multiple allocations per second. – Konstantin Posudevskiy Feb 09 '17 at 10:06
  • @xanatos It can halt the CPU for the time before it can do the switch (which mostly happens on a timer interrupt, so no problem), but that would only help power usage, not other threads running on the system. And then you'd have to wait for some other thread to relinquish the CPU before you could run again, which simply isn't going to happen. – Luaan Feb 09 '17 at 10:34

1 Answers1

3

The only way to "stop" a CPU is to halt it - and that's a kernel-level instruction on Windows. The only way to wake a CPU is to give it an interrupt - again, kernel-level. While it's possible to create a timer interrupt with far higher accuracy than milliseconds on x86, you'd need to make your own OS (possibly virtualized - if it uses the CPU exclusively) to use it.

On application-level, you need to rely on the available interfaces entirely. And you need to coöperate with other processes running on the same CPU/OS. This means you need to use the OS task scheduling - and Windows task scheduling has limits. The shortest interval you could possibly wait for depends on what the OS allows - and on Windows, this used to be related to the system timer (~20ms, configurable down to 0.5ms). But even with the newer schedulers, you can't just arbitrarily schedule a thread to run with microsecond accuracy.

If you need such hard-realtime environments, you simply can't use Windows, or any other preëmptively multi-tasked system, really. Sleeping every other half-a-millisecond is already pushing the realistic capabilities of modern systems running hundreds of processes with thousands of threads at the same time. Busy-waiting can get you close (and indeed is still used in games) if you can afford that thread to pretty much claim the CPU for itself - otherwise, other threads can easily steal the CPU from your thread (easily 20ms or more). Of course, it will still quickly fail if the system gets under significant load.

As always, it's a game of trade-offs. Making a modern multi-tasked system that could schedule threads with such accuracy would be possible, but isn't really worth it. Even in old games with exclusive CPU access, you usually wouldn't "sleep for 20us" - instead, you'd wait for a vertical retrace interrupt or something like that (and this is still somewhat available in DirectX/OpenGL/Vulkan...). There's very few applications that would require both a modern multi-tasked system, and a scheduler accuracy that high. In most user applications, you can use an algorithm that allows you to sleep 25% of the time without switching thread contexts every 20us (e.g. doing more work every "frame", and sleeping accordingly longer).

Luaan
  • 62,244
  • 7
  • 97
  • 116