python 的 time.sleep() 有多准确?
- 2024-12-20 08:37:00
- admin 原创
- 81
问题描述:
我可以给它浮点数,例如
time.sleep(0.5)
但它有多准确?如果我给它
time.sleep(0.05)
它真的会睡眠大约 50 毫秒吗?
解决方案 1:
该函数的精度time.sleep
取决于底层操作系统的睡眠精度。对于非实时操作系统(如普通 Windows),您可以睡眠的最小间隔约为 10-13 毫秒。我曾见过在高于最低 10-13 毫秒时,睡眠时间精确到该时间的几毫秒之内。
更新:就像下面引用的文档中提到的那样,循环进行睡眠是很常见的,如果它让你早早醒来,它就会确保重新进入睡眠状态。
我还应该提到,如果您正在运行 Ubuntu,您可以通过安装rt 内核包(至少在 Ubuntu 10.04 LTS 中)来试用伪实时内核(使用RT_PREEMPT补丁集)。
非实时 Linux 内核的最小睡眠间隔更接近 1ms 而不是 10ms,但它以不确定的方式变化。
解决方案 2:
人们对操作系统和内核之间的差异的看法非常正确,但我在 Ubuntu 中没有看到任何粒度,在 MS7 中我看到了 1 毫秒的粒度。建议对 time.sleep 进行不同的实现,而不仅仅是不同的滴答率。顺便说一句,仔细检查表明 Ubuntu 中的粒度为 1μs,但这是由于我用于测量准确性的 time.time 函数。
解决方案 3:
以下是我对威尔伯特的回答的跟进:对于 Mac OS X Yosemite 来说也是如此,因为还没有太多提到它。
看起来很多时候它的休眠时间约为您请求时间的 1.25 倍,有时休眠时间介于您请求时间的 1 到 1.25 倍之间。它几乎从不(约 1000 个样本中的两次)休眠时间明显超过您请求时间的 1.25 倍。
此外(未明确显示),1.25 关系似乎保持得很好,直到低于约 0.2 毫秒,之后它开始变得有点模糊。此外,在请求的时间量超过 20 毫秒后,实际时间似乎稳定在比您请求的时间长约 5 毫秒。
再次,它在 OS X 中的实现似乎sleep()
与在 Windows 或 Wilbert 使用的 Linux 内核中的实现完全不同。
解决方案 4:
来自文档:
另一方面,
time()
和的精度sleep()
优于它们的 Unix 等效项:时间表示为浮点数,
time()
返回最准确的可用时间(gettimeofday
在可用时使用 Unix),并且sleep()
接受非零分数的时间(select
在可用时使用 Unix 来实现这一点)。
更具体地说sleep()
:
暂停执行给定的秒数。参数可以是浮点数,以指示更精确的休眠时间。实际暂停时间可能小于请求的时间,因为任何捕获的信号都会终止该信号的捕获例程的后续执行。此外,由于系统中其他活动的调度,
sleep()
暂停时间可能比请求的时间长任意长。
解决方案 5:
如果您需要更高的精度或更低的睡眠时间,并且不介意等待时的忙循环(100%的 CPU 核心使用率),请考虑自己制作:
import time
def sleep(duration, get_now=time.perf_counter):
now = get_now()
end = now + duration
while now < end:
now = get_now()
解决方案 6:
你为什么不去发现呢:
from datetime import datetime
import time
def check_sleep(amount):
start = datetime.now()
time.sleep(amount)
end = datetime.now()
delta = end-start
return delta.seconds + delta.microseconds/1000000.
error = sum(abs(check_sleep(0.050)-0.050) for i in xrange(100))*10
print "Average error is %0.2fms" % error
记录一下,我的 HTPC 上的误差约为 0.1ms,笔记本电脑上的误差约为 2ms,这两台机器都是 Linux 机器。
解决方案 7:
该time.sleep
方法在即将发布的 Python (3.11) 版本中经过了大量重构。现在 Windows 和 Unix 平台上都可以获得类似的准确度,并且默认情况下始终使用最高精度。以下是新文档的相关部分:
在 Windows 上,如果 secs 为零,则线程将其时间片的剩余部分让给任何其他准备运行的线程。如果没有其他准备运行的线程,则该函数立即返回,线程继续执行。在 Windows 8.1 及更高版本上,实现使用高精度计时器,精度为 100 纳秒。如果 secs 为零,则使用 Sleep(0)。
Unix 实现:
如果可用,请使用clock_nanosleep()(分辨率:1纳秒);
或者使用 nanosleep()(如果可用)(分辨率:1 纳秒);
或者使用select()(分辨率:1微秒)。
因此,从 python 3.11 开始,在大多数平台上只需调用time.sleep
即可,这是个好消息!最好对这个新实现进行类似于 @wilbert 的跨平台基准测试。
解决方案 8:
一个小更正,有几个人提到可以通过信号提前结束睡眠。在3.6 文档中,它说,
在 3.5 版更改: 即使睡眠被信号中断,该函数现在也会睡眠至少 secs,除非信号处理程序引发异常(请参阅PEP 475了解基本原理)。
解决方案 9:
time.sleep() 的高精度变体。
逻辑:time.sleep() 的精度低于 5ms,因此给定一个时间窗口(例如 1 秒),它会将剩余时间分成 remaining_time / 2,每次迭代将睡眠时间减半。当它达到 < 20ms 时,它会移动到 while 循环(CPU 密集型),然后在剩余时间 < 0ms 时中断。
import time
def high_precision_sleep(duration):
start_time = time.perf_counter()
while True:
elapsed_time = time.perf_counter() - start_time
remaining_time = duration - elapsed_time
if remaining_time <= 0:
break
if remaining_time > 0.02: # Sleep for 5ms if remaining time is greater
time.sleep(max(remaining_time/2, 0.0001)) # Sleep for the remaining time or minimum sleep interval
else:
pass
时间测试:
script_start_time = time.perf_counter()
time.sleep(1)
time_now = time.perf_counter()
elapsed_time = (time_now - script_start_time) * 1000
print("[%.6f] time.sleep" % elapsed_time)
script_start_time = time.perf_counter()
high_precision_sleep(1)
time_now = time.perf_counter()
elapsed_time = (time_now - script_start_time) * 1000
print("[%.6f] high_precision_sleep" % elapsed_time)
结果:
[1007.893800] time.sleep
[1000.004200] high_precision_sleep
解决方案 10:
您实际上无法保证有关 sleep() 的任何事情,除了它至少会尽最大努力按照您的指示睡眠(信号可以在时间到之前终止您的睡眠,还有许多其他事情可以使其运行很长时间)。
当然,在标准桌面操作系统上可以获得的最小值将在 16 毫秒左右(计时器粒度加上上下文切换时间),但当您尝试睡眠 10 毫秒时,与所提供参数的百分比偏差可能会很大。
信号、持有 GIL 的其他线程、内核调度、处理器速度步进等都可能严重影响线程/进程实际休眠的持续时间。
解决方案 11:
def test():
then = time.time() # get time at the moment
x = 0
while time.time() <= then+1: # stop looping after 1 second
x += 1
time.sleep(0.001) # sleep for 1 ms
print(x)
在 Windows 7 / Python 3.8 上1000
,即使我将睡眠值设置为0.0005
因此,至少对于这个特定设置来说,1ms 是完美的
编辑 2024:
在 Win10 / Python 3.9.2 上再次运行此测试,它返回66
(15ms)。
除非将睡眠持续时间设置为0
,
在这种情况下,它只会返回 200 万以上的某个值,因为它会跳过睡眠
解决方案 12:
def start(self):
sec_arg = 10.0
cptr = 0
time_start = time.time()
time_init = time.time()
while True:
cptr += 1
time_start = time.time()
time.sleep(((time_init + (sec_arg * cptr)) - time_start ))
# AND YOUR CODE .......
t00 = threading.Thread(name='thread_request', target=self.send_request, args=([]))
t00.start()
不要使用变量传递 sleep() 的参数,必须将计算直接插入到 sleep() 中
我的终端回归了
1 ────── 17:20:16.891 ────────────────────
2 ────── 17:20:18.891 ────────────────────
3 ────── 17:20:20.891 ────────────────────
4 ────── 17:20:22.891 ────────────────────
5 ────── 17:20:24.891 ────────────────────
....
689 ──── 17:43:12.891 ────────────────────
690 ──── 17:43:14.890 ────────────────────
691 ──── 17:43:16.891 ────────────────────
692 ──── 17:43:18.890 ────────────────────
693 ──── 17:43:20.891 ────────────────────
...
727────17:44:28.891────────────────────
728────17:44:30.891────────────────────
729 ──── 17:44:32.891 ────────────────────
730 ──── 17:44:34.890 ────────────────────
731 ──── 17:44:36.891 ────────────────────
解决方案 13:
最近在 Windows 10 上的 Python 3.7 上进行了测试。精度约为 1ms。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理必备:盘点2024年13款好用的项目管理软件