循环中使用time.perf_counter_ns()导致CPU负载过高,求轻量级毫秒级计时替代方案
兄弟,先给你澄清个误区:time.perf_counter_ns()本身一点都不占资源,真正把CPU拉满让风扇狂转的,是你那个不带任何停顿的while True无限循环!
你想啊,这个循环会让CPU核心一刻不停地跑,连喘口气的机会都没有——哪怕是性能再强的PC,单个核心被这种空循环占满,风扇也会立刻响起来。你之前排查的时候可能没注意到这一点,错把锅甩给了计时函数。
给你几个简单有效的解决办法,亲测能把CPU负载打下来:
给循环加个短暂的sleep(最推荐)
只需要在循环末尾加一行time.sleep(0.001)(也就是1毫秒的停顿),就能让CPU在空闲时间去处理其他任务,负载会直接降到几乎可以忽略的程度。而且对于你500ms间隔的任务来说,1ms的停顿完全不会影响精度。修改后的代码大概是这样:import time last_time_ns = time.perf_counter_ns() while True: # 执行你的常规操作 current_time_ns = time.perf_counter_ns() elapsed_time_ms = (current_time_ns - last_time_ns) / 1_000_000 if elapsed_time_ms > 500: print("do something every 500 ms") last_time_ns = current_time_ns # 让CPU喘口气的关键一行 time.sleep(0.001)换用更简洁的单调计时函数
如果你觉得perf_counter_ns()的单位换算麻烦,可以换成time.monotonic()——它同样是单调递增的计时函数(不会因为系统时间调整而跳变,适合做间隔计时),返回的是秒级浮点数,计算起来更方便,开销和perf_counter_ns()几乎一样。示例代码:import time last_time = time.monotonic() while True: # 执行你的常规操作 current_time = time.monotonic() if current_time - last_time > 0.5: print("do something every 500 ms") last_time = current_time time.sleep(0.001)直接sleep到下一个任务执行点(适合操作耗时短的场景)
如果你的常规操作本身耗时很短,还可以计算距离下一次执行500ms任务还剩多久,直接sleep那段时间,这样循环的频率会更低,CPU负载几乎为0:import time interval = 0.5 # 500ms last_time = time.monotonic() while True: # 执行你的常规操作 current_time = time.monotonic() elapsed = current_time - last_time if elapsed > interval: print("do something every 500 ms") last_time = current_time # 计算剩余等待时间,直接sleep time.sleep(max(0, interval - elapsed - 0.001))
总结一下:别再怪perf_counter_ns()了,它真的很轻量。核心问题是无停顿的无限循环,加个几毫秒的sleep就能解决99%的问题,计时函数用perf_counter_ns()或者time.monotonic()都完全没问题。
内容来源于stack exchange

