【问题标题】:Why time.sleep() is so slow in Windows?为什么 time.sleep() 在 Windows 中这么慢?
【发布时间】:2017-03-28 10:26:42
【问题描述】:

我循环 1000 次,延时 1ms 并计算总时间。有趣的是,总时间是 15.6 秒而不是 1 秒。当我打开谷歌浏览器并浏览一些网站时,它运行正常,总共 1 秒。此外,它在 Macbook 上也运行良好。 我想知道我需要采取什么样的解决方案来解决这个问题?请尝试在没有打开 Chrome 的情况下运行它,然后在打开 Chrome 的情况下再次运行它以查看差异。当 Quora 或 Reddit 或 Stackoverflow 在我的系统上打开时,它可以正常运行。

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)

编辑:我没有在 Python 上运行它。我刚刚打开Chrome浏览了一些网站来加快延时。

更新:这是关于 Windows 的计时器分辨率。所以基本上,Chrome 将计时器分辨率从 15.6 毫秒更改为 1 毫秒。这篇文章解释的很好:https://randomascii.wordpress.com/2013/07/08/windows-timer-resolution-megawatts-wasted/

【问题讨论】:

  • 你是如何在 chrome 中运行 python 的?这非常令人困惑。
  • 您的错误是假设sleep(0.001) 将休眠一毫秒,而不仅仅是至少 1ms。您可能想阅读stackoverflow.com/questions/9518106
  • 致 Eli:我没有在 Python 上运行它。我刚刚打开 Chrome 浏览了一些网站以加快时间延迟。很抱歉造成混乱。
  • @IkerHua:为什么会增加延时?
  • -Jon:我知道它不会精确到毫秒。但不确定性是巨大的。当我在 Chrome 打开时运行它时,循环 1000 次需要 1.003 秒。 Chrome 未打开时,循环 1000 次需要 15.6 秒。这两个试验之间的代码没有修改。这是最让我困惑的地方。

标签: windows multithreading python-3.x


【解决方案1】:

我终于明白了。非常感谢cmets。这些给了我解决它的提示。为了解释为什么会发生这种情况,Windows 操作系统将其默认计时器分辨率设置为 15.625 毫秒或 64 赫兹,这对于大多数应用程序来说已经足够了。但是,对于需要非常短的采样率或时间延迟的应用,15.625 ms 是不够的。因此,当我自己运行我的程序时,它在 15.6 秒时停留了 1000 个点。但是,当 Chrome 打开时,更高分辨率的计时器被触发并更改为 1 毫秒而不是 15.6,这导致我的程序按预期运行。

因此,为了解决这个问题,我需要调用一个名为timeBeginPeriod(period) 的Windows 函数来更改分辨率计时器。幸运的是,python 通过提供ctypes 库让我很容易修复它。最终代码如下:

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)

警告:我了解到这种高计时器分辨率将如何影响整体性能以及电池。我还没有看到任何事情发生,并且 Windows 任务管理上的活动 CPU 使用率似乎也没有压倒一切。但是,如果您的应用程序碰巧导致一些奇怪的行为,请记住这一点。

【讨论】:

  • A cleaner implementation 具有错误检查和上下文管理功能。当然,这对于任何关键的东西来说都是不可靠的,因为它受系统上运行的其他软件的支配。如果您需要关键时间,最好使用time.perf_counter() 忙循环,而不是依赖系统调度程序。
  • @eryksun:嗨,eryksun,感谢您的建议。你的方法能保证每个周期的准确时间延迟吗?我的仍然关闭了 0.1 或 0.2 毫秒,这有点糟糕,因为我的应用程序是以恒定速率绘制点。稍微偏离速度就会使情节看起来非常糟糕。
  • 在 Windows 上,timer.perf_counter 调用 QueryPerformanceCounter,这是一个至少具有 1 微秒分辨率的单调时钟。检查time.get_clock_info('perf_counter')
  • 我阅读并认为timer.perf_counter 非常强大和准确。但是如何在 python 中使用time.perf_counter() 来延迟或休眠呢?我的理解是它只能用来测量时差。
  • “睡眠”必然涉及内核调度程序,这使您受制于系统计时器分辨率。如果您需要精度,则只需循环一段时间,例如deadline = time.perf_counter() + period;while time.perf_counter() < deadline: pass.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-10-29
  • 2010-11-12
  • 2011-12-06
  • 1970-01-01
  • 1970-01-01
  • 2021-09-03
  • 1970-01-01
相关资源
最近更新 更多