0

I need to create software that needs to poll hardware device.

static void Main(string[] args)
{
    while(true)
    {
        DoSomething();
        Task.Delay(1).Wait();
    }
}

static void DoSomething(){}

I noticed that if I don't add even a smallest delay then CPU usage goes to 30-40%, but even with 1ms delay the usage remains around couple of percent.

My development environment is .net/c#.

For me and business it doesn't feel necessary to add 1ms delay, but it seems to make a world of a difference.

It feels like it is a good idea to add even a tiny delay. Why?

EDIT:

Given that piece of code above, with empty DoSomething(), why adding Task.Delay(1).Wait(); draws down CPU usage so much? It feels such a trivial thing. How come it has such an impact?

Siim Haas
  • 485
  • 2
  • 6
  • 15
  • 3
    That's not a tiny delay. 1ms is a very long time as far as processors are concenred. What does `DoSomething()` do? If it takes 1ms, you have a 50% reduction in CPU usage – Panagiotis Kanavos Oct 04 '18 at 09:13
  • When you don't have any delays your DoSomething method is called as fast as possible, without any rest your CPU is working for it. But when you add your 1ms delay, then there is 1 ms (10 000 cpu ticks) that the CPU is resting from your method. – Markiian Benovskyi Oct 04 '18 at 09:13
  • 3
    BTW that 1ms delay is more like 15.6 ms, the default resolution of timers on Windows. Even when you specify 1ms, the delay will be 15.6 at least – Panagiotis Kanavos Oct 04 '18 at 09:15
  • If you don't add a delay you just execute the DoSomething() in a loop. When you add the delay, a continuation is created and the execution of the loop is halted for a period. Notice that period is not 1 ms, as the resolution of timers on Windows is not that small. The default resolution is 15.6 ms (a timer interrupt 64 times a second). – Marius Bancila Oct 04 '18 at 09:17
  • How often do you really want to poll each device? What devices? Some can't be polled that fast for example. If you *do* need fast polling, you could change the system's timer resolution at the cost of increased power usage. Chrome is notorious for doing this. On the other hand, multimedia services like video, audio, that require far faster timers use special services and APIs to work. – Panagiotis Kanavos Oct 04 '18 at 09:23
  • What is the actual question... Why does it go from 40 to a few percent, or is it a good idea or not? – TheGeneral Oct 04 '18 at 09:26
  • Check [this question](https://stackoverflow.com/questions/24839105/high-resolution-timer-in-c-sharp) that shows how to use the [multimedia timers](https://stackoverflow.com/questions/24839105/high-resolution-timer-in-c-sharp) in .NET through interop. These have a resolution of 1ms BUT read [this too](https://stackoverflow.com/questions/20343099/understanding-the-strange-behavior-of-multimedia-timer) – Panagiotis Kanavos Oct 04 '18 at 09:26
  • @SlimHaas the edit asks stuff that was already answered in the comments. Without the wait, you peg a core at 100% running that loop. With a delay, you only use the CPU when the timer fires. That's 60 times per second max. *Don't* use a tight loop if you don't have to. If you *have* to, there are other ways to do it – Panagiotis Kanavos Oct 04 '18 at 09:33

2 Answers2

3

Let's say DoSomething takes 0.1 ms. Then, without the delay, it is executed 10_000 times per second. With the delay it is executed less than 900 times per second. As noted in the comments, the actual delay depends on the OS and can be 15.6 ms, so you may have ~60 calls per second in fact.

So the amount of work the CPU has to do differs dramatically.

Pavel Tupitsyn
  • 8,393
  • 3
  • 22
  • 44
2

Writing something like

while (true)
{
    DoSomething();   
}

you're effectively telling the compiler to build a code that can be translated to the human language like this:

Dear CPU, please do as fast as you can DoSomething().

This is the explanation of why the CPU load drops when you add even a tiny delay. Because then, the code will be translated in something like:

Dear CPU, please do DoSomething(), and then you can rest for millions of cycles. After that, do DoSomething() again.

Note that 1 ms is a lot for a CPU working at a 2-4 GHz frequency.

dymanoid
  • 14,771
  • 4
  • 36
  • 64