Is `asyncio.sleep(delay)` guarenteed to sleep for at least `delay` seconds?(“asyncio.sleep(Delay)”是否保证睡眠至少需要“delay”秒?)
问题描述
asyncio.sleep()
的阻塞表亲time.sleep()无法保证它将休眠请求的时间。
实际挂起时间可能小于请求的时间,因为任何捕获的信号都将在执行该信号的捕获例程后终止SLEEP()。
asyncio.sleep()
%sdocumentation没有提到类似的限制。
asyncio.sleep()
是否能够对休眠时间做出更强有力的保证?
推荐答案
我不会说asyncio
保证,但根据实现可以得出结论:asyncio.sleep()
(基本上是call_later()
)在指定的时间间隔内休眠,但至少不精确到实现中使用的系统时钟的分辨率。
让我们把它弄清楚。首先,asyncio
使用单调时钟,其分辨率on different platforms不同(Python和OS分辨率)。例如,对于Windows
,这与15ms
一样多。
保证方面,请注意函数备注BaseEventLoop.time
:
def time(self):
"""Return the time according to the event loop's clock.
This is a float expressed in seconds since an epoch, but the
epoch, precision, accuracy and drift are unspecified and may
differ per event loop.
"""
return time.monotonic()
现在让我们看一下负责启动计划计时器的asyncio
事件循环源code:
# Handle 'later' callbacks that are ready.
end_time = self.time() + self._clock_resolution
while self._scheduled:
handle = self._scheduled[0]
if handle._when >= end_time:
break
handle = heapq.heappop(self._scheduled)
handle._scheduled = False
self._ready.append(handle)
end_time = self.time() + self._clock_resolution
行end_time = self.time() + self._clock_resolution
显示回调可能比计划提前,但在时钟分辨率范围内。尤里·谢利万诺夫对此明确表示here:
在我看来,目前我们可以窥视未来的时间。我们为什么不这样做
end_time = self.time() - self._clock_resolution
是否保证超时总是在请求的时间之后而不是之前触发?如果我们这样做,我看不出性能会变得更差。
实际上,让我们运行下一个程序(Windows10上的Python 3.8):
import asyncio
import time
async def main():
print("Timer resolution", time.get_clock_info('monotonic').resolution)
while True:
asyncio.create_task(asyncio.sleep(1))
t0 = time.monotonic()
await asyncio.sleep(0.1)
t1 = time.monotonic()
print(t1 - t0)
asyncio.run(main())
我们看到上述行为:
Timer resolution 0.015625
0.09299999987706542
0.0940000000409782
0.0940000000409782
0.10900000017136335
...
但在正文的开头,我说了至少是时钟分辨率,因为asyncio
工作在协作多任务的条件下,如果有一个贪婪的协程程序(或许多不太贪婪的协程程序)不能太频繁地控制事件循环,我们会看到下面的图片:
import asyncio
import time
async def calc():
while True:
k = 0
for i in range(1*10**6):
k += i
await asyncio.sleep(0.1) # yield to event loop
async def main():
asyncio.create_task(calc()) # start greedy coroutine
print("Timer resolution", time.get_clock_info('monotonic').resolution)
while True:
asyncio.create_task(asyncio.sleep(1))
t0 = time.monotonic()
await asyncio.sleep(0.1)
t1 = time.monotonic()
print(t1 - t0)
asyncio.run(main())
情况不出所料地朝着增加延迟的方向变化:
0.17200000025331974
0.1559999999590218
0.14100000029429793
0.2190000000409782
这篇关于“asyncio.sleep(Delay)”是否保证睡眠至少需要“delay”秒?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:“asyncio.sleep(Delay)”是否保证睡眠至少需要“delay”秒?
基础教程推荐
- 哪些 Python 包提供独立的事件系统? 2022-01-01
- Python 的 List 是如何实现的? 2022-01-01
- 如何在Python中绘制多元函数? 2022-01-01
- 使用 Google App Engine (Python) 将文件上传到 Google Cloud Storage 2022-01-01
- 使 Python 脚本在 Windows 上运行而不指定“.py";延期 2022-01-01
- 将 YAML 文件转换为 python dict 2022-01-01
- 症状类型错误:无法确定关系的真值 2022-01-01
- 合并具有多索引的两个数据帧 2022-01-01
- 使用Python匹配Stata加权xtil命令的确定方法? 2022-01-01
- 如何在 Python 中检测文件是否为二进制(非文本)文 2022-01-01