列表创建时计时器是否应捕获完整耗时?
Python计时上下文管理器后的延迟问题解析
先看你写的代码:
from time import perf_counter class catchtime: def __enter__(self): self.start = perf_counter() return self def __exit__(self, type, value, traceback): self.time = perf_counter() - self.start self.readout = f"Time: {self.time:.3f} seconds" print(self.readout) with catchtime() as timer: a = [1] * 1000000000 print(1) print(timer.readout)
现象原因
- 你创建的列表
a包含10亿个元素,占用了巨量内存(Python里单个int对象远大于4字节,实际这个列表可能占几十GB内存)。 with块结束后,变量a失去作用域变成垃圾对象,但Python的垃圾回收不会立刻处理这么大的对象。- 程序终止前,Python会强制清理所有剩余变量,触发大对象的内存释放——这个过程需要操作系统回收对应的内存页,所以会产生明显的等待延迟,而这段时间不在上下文管理器的计时范围内(因为
__exit__已经执行完了)。
是否应捕获这段完整耗时?
完全看你的计时需求:
- 如果是测量业务逻辑的执行时间(也就是创建列表+打印1的时间),那不需要捕获这段延迟——因为这属于程序收尾的系统级开销,和你要测的代码逻辑无关。
- 如果是测量从程序启动到完全退出的总耗时,那必须把计时范围覆盖到整个程序生命周期。比如可以在程序最开头记录起始时间,用
atexit钩子在程序退出前计算总耗时:
from time import perf_counter import atexit # 记录程序启动时间 total_start = perf_counter() def show_total_time(): total = perf_counter() - total_start print(f"程序总耗时: {total:.3f} 秒") # 注册退出时执行的函数 atexit.register(show_total_time) # 你的原有计时类 class catchtime: def __enter__(self): self.start = perf_counter() return self def __exit__(self, type, value, traceback): self.time = perf_counter() - self.start self.readout = f"逻辑执行时间: {self.time:.3f} 秒" print(self.readout) with catchtime() as timer: a = [1] * 1000000000 print(1) print(timer.readout)
内容的提问来源于stack exchange,提问作者ilovewt
相关产品推荐
相关产品推荐

