kohi
kohi copied to clipboard
[#75] Increase Windows sleep accuracy beyond 64 ticks per second
Addresses #75
Increases the accuracy of the underlying timer device while sleeping in order to allow for more accurate thread sleeps on Windows.
"Sleep() is accurate to the operating system's clock interrupt rate. Which by default on Windows ticks 64 times per second. Or once every 15.625 msec, as you found out. You can increase that rate, call timeBeginPeriod(10). Use timeEndPeriod(10) when you're done. You are still subject to normal thread scheduling latencies so you still don't have a guarantee that your thread will resume running after 10 msec. And won't when the machine is heavily loaded. Using SetThreadPriority() to boost the priority, increasing the odds that it will."
However instead of using a hardcoded value, this fix queries the minimum period of the underlying hardware timer via timeGetDevCaps()
in the clock_setup()
function.
Note that the sleep time does still seem to be quite unreliable, and it seems its because getting reliable timings on Windows can be notoriously difficult. Apparently using Sleep()
is not really recommended for these kinds of applications. Would have to look further into that. I've seen some ideas floating around about combining sleeping with spinlocking as a potential way to increase accuracy (at the cost of more CPU usage).
Found a pretty accurate sleep function implementation here: https://blat-blatnik.github.io/computerBear/making-accurate-sleep-function/. Could potentially look into using something similar. I tested this with Kohi's clock implementation, and it seems to work really well.
Update: I emailed the author of the aforementioned blog post after noticing some adjustments that could be made to his accurate sleep function, and he ended up following up by creating the following, more up-to-date blog post detailing a better sleep function: https://blog.bearcats.nl/perfect-sleep-function/
The blog mentions how newer versions of Windows 10/11 support timers, which can be preferable as they don't affect global state (changing scheduler period is global state. Setting this below 8 ms is known to cause significantly higher power usage on other applications, which I try to mitigate by only setting it when calling Sleep), however not sure it's wise to use them since it's only on these newer builds of Win 10/11.
Rebased to fix conflicts
Switched branches and merged. Thank you!