Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why time.sleep() is so slow in Windows?

I'm looping 1000 times with time delay 1ms and calculating total time. It's very interesting how the total time is 15.6 seconds instead of 1. When I opened Google Chrome and surfed some websites, it ran correctly with 1 sec total. Also, it ran fine with Macbook too. I'm wondering what kind of solutions that I need to do to fix this problem? Please try to run it without Chrome opened an again with Chrome opened to see the difference. It ran normally when Quora or Reddit or Stackoverflow opened on my system.

from timeit import default_timer as timer
import time
start = timer()
for i in range(1000):
    time.sleep(0.001)

end = timer()
print ("Total time: ", end - start)

Edit: I didn't run it on Python. I just opened up Chrome and browsed some websites to speed up the time delay.

Updated: It's about the timer resolution from Windows. So basically, Chrome changed the timer resolution from 15.6ms to 1ms. This article explains very well: https://randomascii.wordpress.com/2013/07/08/windows-timer-resolution-megawatts-wasted/

like image 829
Iker Hua Avatar asked Nov 14 '16 17:11

Iker Hua


1 Answers

I finally figured it out. Thanks a lot for the comments. Those gave me hints to solve it. To explain why this happened, Windows OS has its default timer resolution set to 15.625 ms or 64 Hz, which is decently enough for most of the applications. However, for applications that need very short sampling rate or time delay, then 15.625 ms is not sufficient. Therefore, when I ran my program itself, it's stuck at 15.6 s for 1000 points. However, when Chrome is opened, the higher resolution timer is triggered and changed to 1 ms instead of 15.6, which caused my program to run as expected.

Therefore, in order to solve it, I needed to call a Windows function named timeBeginPeriod(period) to change the resolution timer. Fortunately, python made it easy for me to fix it by providing ctypes library. The final code is provided below:

from time import perf_counter as timer
import time
from ctypes import windll #new

timeBeginPeriod = windll.winmm.timeBeginPeriod #new
timeBeginPeriod(1) #new

start = timer()
for i in range(1000):
    print (i)
    time.sleep(0.001)

end = timer()
print ("Total time: ", end - start)

Warning: I read about how this high timer resolution will affect the overall performance and also the battery. I have not seen anything happening yet, and CPU Usage on Activity on Windows Task Manage doesn't seem to overwhelming either. But keep that in mind if your applications happen to cause some strange behaviors.

like image 86
Iker Hua Avatar answered Oct 18 '22 10:10

Iker Hua