如何实现毫秒级精度指定时间调用函数,消除或固定执行延迟?
毫秒级定时执行的优化方案
你遇到的延迟主要来自两个核心原因:
- 普通操作系统的
time.sleep默认是可中断的低精度睡眠,用户态进程的调度粒度通常在10~100ms区间,睡眠结束后还需要等待CPU调度才能执行后续代码 - 单次长睡眠的计时误差、目标时间计算的微小开销也会叠加延迟
方案1:混合睡眠+忙等待(推荐,精度最高可到1ms内)
不要一次性睡到目标时间,拆分为两个阶段:
- 剩余时间大于10ms时,用1ms级的短睡眠让出CPU,降低资源占用
- 剩余时间小于1ms时,进入纯忙等待循环判断时间,消除调度延迟
示例代码如下:
import time from datetime import datetime def run_at(target_time): # 先把目标时间转成时间戳(毫秒级精度) target_ts = time.mktime(target_time.timetuple()) + target_time.microsecond / 1e6 while True: now_ts = time.time() diff = target_ts - now_ts if diff <= 0: break # 剩余时间大于10ms就睡1ms,否则忙等 if diff > 0.01: time.sleep(0.001) # 到点执行目标代码 print(datetime.now().strftime('%H:%M:%S.%f')[:-3]) # 测试 tt = datetime(2021, 8, 22, 3, 17, 00) run_at(tt)
这个方案在普通PC上测试,延迟通常可以控制在±2ms以内,唯一的缺点是最后1ms会占满1个CPU核心,对资源占用敏感的场景可以根据需求调整忙等待的阈值。
方案2:校准固定偏移量(适合需要恒定延迟的场景)
如果你的运行环境相对稳定,可以先跑10~20次测试统计平均延迟,比如你当前环境平均延迟是38ms,那直接在目标等待时间里减去这个固定偏移量即可:
tt = datetime(2021, 8, 22, 3, 17, 00) offset = 0.038 # 你自己测出来的平均延迟 wait_time = time.mktime(tt.timetuple()) - time.time() - offset if wait_time > 0: time.sleep(wait_time) print(datetime.now().strftime('%H:%M:%S.%f')[:-3])
这个方案不会额外占用CPU,但精度受环境波动影响较大,适合负载稳定的服务器环境。
额外优化建议
- 提升进程优先级:Windows下可以用
psutil.Process().nice(psutil.REALTIME_PRIORITY_CLASS),Linux下执行nice -n -20 python 你的脚本.py,甚至配置实时调度策略,能大幅降低调度带来的延迟波动 - 不要在定时执行前跑其他重负载代码,避免CPU缓存被占、GC触发等额外开销
- 普通桌面操作系统最多能做到1ms左右的精度,如果需要微秒级精度,必须使用实时操作系统。
内容的提问来源于stack exchange,提问作者Amin DM
相关产品推荐
相关产品推荐

