Why does Sleep () slow down subsequent code by 40 ms?

I originally asked about this on coderanch.com, so if you tried to help me there, thank you and don't feel obligated to repeat the effort. coderanch.com is basically the Java community, and it seems (after some research) really a Windows issue, so my colleagues are there, and I thought it might be a better place to look for help.

I wrote a short program that either spins on the Windows performance counter until 33 ms has passed, or calls "Sleep" (33). The former does not show any unexpected effects, but the latter apparently (steadily) slows down subsequent processing for about 40 ms (either this or has some effect on the values โ€‹โ€‹returned from the performance counter for this long). After rotation or sleep (), the program calls the runInPlace () procedure, which rotates for 2 ms, counting the number of requests to the performance counter and returning this number.

When the initial 33 ms delay is performed by rotation, the number of iterations of runInPlace (), as a rule (on my Windows 10, XPS-8700), is about 250,000. It changes, probably due to other system overheads, but it changes the smoothing about 250,000.

Now that the initial delay is done by calling Sleep (), something strange is happening. Many calls to runInPlace () return a number around 250,000, but many of them return a number around 50,000. Again, the range is around 50,000, pretty smoothly. But, obviously, he averages one or another, almost anywhere from 80,000 to 150,000 people return. If I call runInPlace () 100 times after each delay, and not just once, it will never return the number of iterations in a smaller range after the 20th call. Since runInPlace () runs for 2 ms, this means that the behavior that I am observing disappears after 40 ms. If I run runInPlace () in 4 ms instead of 2 ms, it never returns the number of iterations in a smaller range after the 10th call, so again the behavior disappears after 40 ms (similarly, if runInPlace () only works for 1 ms; behavior disappears after the 40th call).

Here is my code:

#include "stdafx.h" #include "Windows.h" int runInPlace(int msDelay) { LARGE_INTEGER t0, t1; int n = 0; QueryPerformanceCounter(&t0); do { QueryPerformanceCounter(&t1); n++; } while (t1.QuadPart - t0.QuadPart < msDelay); return n; } int _tmain(int argc, _TCHAR* argv[]) { LARGE_INTEGER t0, t1; LARGE_INTEGER frequency; int n; QueryPerformanceFrequency(&frequency); int msDelay = 2 * frequency.QuadPart / 1000; int spinDelay = 33 * frequency.QuadPart / 1000; for (int i = 0; i < 100; i++) { if (argc > 1) Sleep(33); else { QueryPerformanceCounter(&t0); do { QueryPerformanceCounter(&t1); } while (t1.QuadPart - t0.QuadPart < spinDelay); } n = runInPlace(msDelay); printf("%d \n", n); } getchar(); return 0; } 

Here's some output typical of what I get when using Sleep () for a delay:

56116 248936 53659 34311 233488 54921 47904 45765 31454 55633 55870 55607 32363 219810 211400 216358 274039 244635 152282 151779 43057 37442 251658 53813 56237 259858 252275 251099

And here are some of the results specific to what I get when I spin to create a delay:

276461 280869 276215 280850 188066 280666 281139 280904 277886 279250 244671 240599 279697 280844 159246 271938 263632 260892 238902 255570 265652 274005 273604 150640 279153 281146 280845 248277

Can someone help me understand this behavior? (Note that I tried this program compiled with Visual C ++ 2010 Express on five computers. This only shows this behavior on the two fastest machines I have.)

+5
source share
2 answers

This seems to be due to the reduced clock speed with which the processor will work when the computer is not busy (SpeedStep). When the computer is in standby mode (for example, in sleep mode), the clock speed will decrease to reduce power consumption. On new processors, this may be 35% or less of the indicated clock frequency. As soon as the computer boots up again, there will be a slight delay before the processor speeds up again.

You can disable this feature (either in the BIOS or by changing the "Minimum processor status" parameter in the "CPU Power Management" section in the advanced settings of your power plan to 100%.

+8
source

In addition to what @ 1201ProgramAlarm said (which may well be, modern processors really like overclocking when they can), it could be a cache loss problem.

When you ask to sleep for a while, the scheduler usually schedules a different thread / process for the next processor time slot, which means that caches (instruction cache, data cache, TLB, branch prediction data, ...) regarding your process will become โ€œcoldโ€ again when your code restores the CPU.

+5
source

Source: https://habr.com/ru/post/1244027/


All Articles