【运行计时】为什么计时不要再用 `time.time()` 了

张开发
2026/4/18 17:30:25 15 分钟阅读

分享文章

【运行计时】为什么计时不要再用 `time.time()` 了
Python 中time.perf_counter()和time.time()的区别​ 很多人在写 Python 代码时如果想统计一段代码运行了多久第一反应通常是importtime starttime.time()# 一段代码endtime.time()print(end-start)​ 这样写看起来没有问题但在真实项目里这其实并不是最推荐的做法。尤其是在下面这些场景中模型推理耗时统计FastAPI 接口耗时监控算法性能测试Benchmark高并发服务中的延迟统计​ 一般来说我更推荐使用time.perf_counter()。那么time.time()和time.perf_counter()到底有什么区别什么时候该用哪个我们下面会进行详细分析。一、time.time()获取当前真实时间​time.time()返回的是当前时间戳。importtimeprint(time.time())​ 输出类似1713156000.123456​ 它表示从 1970 年 1 月 1 日 00:00:00 到现在经过了多少秒。​ 因此time.time()本质上是在告诉你“现在几点了”1.1 典型用途​time.time()更适合做记录日志时间生成时间戳判断某个时间是否超时保存数据库中的时间字段例如importtime log_timetime.time()print(f日志时间{log_time})​ 或者iftime.time()-last_update60:print(距离上次更新时间已经超过 1 分钟)二、time.perf_counter()高精度性能计时器​time.perf_counter()的目标和time.time()完全不同。​ 它不是用来告诉你“现在几点”而是用来告诉你“两段代码之间到底过了多久”importtime starttime.perf_counter()# 一段代码endtime.perf_counter()print(end-start)​ 输出可能是0.0002315​ 这表示代码运行了 0.23 毫秒。2.1 为什么它更适合计时​ 因为time.perf_counter()有两个关键特点。(1)精度更高​ 它通常会使用系统中最精确的时钟。在不同系统上精度可能达到微秒级、纳秒级。​ 例如下面两段代码的差异importtime starttime.time()for_inrange(1000):passprint(time.time()-start)​ 可能输出0.0​ 因为代码执行太快time.time()的精度不够。​ 但如果换成importtime starttime.perf_counter()for_inrange(1000):passprint(time.perf_counter()-start)​ 你就能看到一个更准确的耗时例如0.0000312(2) 不会受到系统时间修改影响​time.time()会读取系统时间。​ 如果你手动修改电脑时间、服务器自动同步 NTP 时间、容器中的系统时间发生变化那么time.time()的结果可能会突然跳变。​ 例如starttime.time()# 执行过程中系统时间被调慢了endtime.time()print(end-start)​ 甚至有可能输出负数-0.8​ 而time.perf_counter()是一个“单调递增”的时钟。它只会不断变大不会倒退。因此它更适合做耗时统计。2.2 两者最直观的区别对比项time.time()time.perf_counter()作用获取当前真实时间统计程序耗时是否受系统时间影响会不会是否单调递增不保证保证精度较低更高是否适合 Benchmark不推荐推荐常见用途日志、时间戳性能测试、接口耗时三、真实项目里应该怎么选3.1 如果你想记录“什么时候发生”​ 那就使用time.time()例如create_time time.time()适用于日志系统数据库存储文件名时间戳3.2 如果你想记录某个过程“花了多久时间”​ 那就用time.perf_counter()进行高精度计时。例如importtime starttime.perf_counter()model.predict(data)latencytime.perf_counter()-startprint(f推理耗时:{latency:.6f}s)​ 这也是模型部署、FastAPI 服务、性能分析中最推荐的写法。四、FastAPI 中统计接口耗时的正确写法​ 很多人在 FastAPI 中会这样写app.get(/predict)defpredict():starttime.time()resultmodel.predict(x)print(time.time()-start)returnresult​ 更推荐importtimefromfastapiimportFastAPI appFastAPI()app.get(/predict)defpredict():starttime.perf_counter()resultmodel.predict(x)costtime.perf_counter()-startprint(f接口耗时:{cost:.6f}s)returnresult​ 这样即使服务器时间被同步、容器时间发生变化耗时统计仍然准确。五、进一步补充还有一个time.process_time()​ 除了这两个函数Python 里还有一个time.process_time()​ 它统计的是CPU 真正执行代码的时间。因此不会统计sleep网络等待数据库等待I/O 等待例如importtime starttime.process_time()time.sleep(1)print(time.process_time()-start)​ 输出可能接近0.0因为 CPU 并没有真正工作。因此想看接口总耗时 → 用perf_counter想分析 CPU 消耗 → 用process_time六、总结# 获取当前时间nowtime.time()# 统计代码耗时starttime.perf_counter()# do somethingcosttime.perf_counter()-start​ 在真实工程里尤其是算法部署、FastAPI、模型推理、接口压测等场景中不要再用time.time()做性能统计而应该优先使用time.perf_counter()。因为它更准确、更稳定也更符合工程实践。

更多文章