本文要点
下面这段只在你自己的练习目录里运行,不读写外部文件、不改系统设置
也就是说,用 time() 量耗时,结果可能因为系统对时、手动改时间等原因出现负值或偏大偏小
如果你的自建操作里有 time.sleep(),要分清两个计时器

本文目录
先分清你要的是“持续多久”还是“几点发生”
如果你只是想量一段自建操作花了多长时间,用 time.perf_counter() 取两次调用的差值就够了。
按 Python 官方 time 模块文档,perf_counter() 返回一个性能计数器的值,单位是秒的小数部分,是“可用来测量短时长的最高可用分辨率时钟”。文档同时写明:它返回值的参考点是未定义的,所以只有两次调用结果之间的差值有意义。
而 time.time() 返回的是自 epoch 起的秒数,是一个浮点数。文档说明 epoch 是时间开始计数的那个点,即 time.gmtime(0) 的返回值,在所有平台上都是 1970 年 1 月 1 日 00:00:00 UTC。
这两句话决定了用途分工:perf_counter 的绝对值没有意义,只能做减法;time() 的绝对值有意义,可以换算成年月日时分秒。所以“这段操作花了多久”用前者,“这件事发生在哪一刻”用后者。
本文只演示计时器差值的简单无副作用计算,不给出任何性能基准结论,也不把示例值当成真实测量结果。
用自建脚本量一段空转:两次 perf_counter 相减
下面这段只在你自己的练习目录里运行,不读写外部文件、不改系统设置。路径请换成你自己的练习相对路径,例如 exercise/。
import time
start = time.perf_counter()
# 这里放你要量的那段操作,下面用一个自建的循环占位
total = 0
for i in range(100000):
total += i
end = time.perf_counter()
print("elapsed:", end - start)输入:一段你自己写的、没有副作用的计算。输出:一个浮点数,表示两次调用之间经过的秒数。
关键点是只取差值。start 和 end 各自的数值在不同机器、不同运行之间都不一样,打印它们本身没有比较意义。文档说得很清楚:参考点未定义,只有差值有效。
如果你需要更细的粒度,文档提供了 perf_counter_ns(),它返回整数纳秒,用来避免浮点类型带来的精度损失。用法一样,也是两次相减。
为什么不用 time.time() 量耗时:它可能被调回去
time.time() 也能做减法,但文档专门提示了一个风险:虽然这个函数通常返回非递减的值,但如果系统时钟在两次调用之间被调回,它可能返回比上一次更小的值。
也就是说,用 time() 量耗时,结果可能因为系统对时、手动改时间等原因出现负值或偏大偏小。而 perf_counter 在 CPython 上使用的是与 time.monotonic() 相同的时钟,文档描述 monotonic 是一个“不能倒退的时钟”,且不受系统时钟更新的影响。
所以判断标准可以简化成一句:
- 要量“经过了多少时间”,且不希望被系统时钟调整干扰,用 perf_counter。
- 要记录“这个时刻对应的日历时间”,用 time(),必要时再用 gmtime() 或 localtime() 换算。
文档还提到,time() 返回的数值可以传给 gmtime() 得到 UTC 的 struct_time,或传给 localtime() 得到本地时间的 struct_time。这是 time() 的用途,不是 perf_counter 的用途。
perf_counter 包含 sleep 时间,process_time 不包含
如果你的自建操作里有 time.sleep(),要分清两个计时器。
文档对 perf_counter 的说明是:它包含 sleep 期间经过的时间。对 process_time 的说明则相反:它返回当前进程的系统 CPU 时间与用户 CPU 时间之和,不包含 sleep 期间经过的时间。
这意味着同一个脚本,用两个计时器量出来的差值回答的是不同问题:
- perf_counter 差值:从开始到结束,墙上过了多久。
- process_time 差值:这段时间里,CPU 真正花在这个进程上多少。
文档对 process_time 也写明参考点未定义,只有两次调用的差值有效,并且它是进程范围的。所以两者都不能拿绝对值去比较,只能各自做减法。
选择方法:你关心“用户等了多久”,用 perf_counter;你关心“CPU 忙了多久”,用 process_time。本文只演示差值计算,不对任何具体数值下结论。
检查结果时先看三件事,再决定要不要重测
拿到一个差值后,不要直接把它当成这段操作的固有耗时。可以按下面顺序检查(以下为编辑整理的检查方向,不是对某台机器的实测记录):
1. 差值是不是负数。如果是,说明你用的很可能是 time() 而不是 perf_counter,或者两次调用的顺序写反了。
2. 差值是不是明显偏大。检查这段操作里有没有包含 sleep、等待输入、网络请求这类会拉长时间的动作。perf_counter 会把 sleep 算进去。
3. 两次调用之间有没有夹进无关代码。把 start 和 end 尽量贴近你要量的那段操作,中间不要放打印、文件读写等额外动作。
文档还提醒了一点:各种实时函数的精度可能低于其数值单位所暗示的精度。例如在多数 Unix 系统上,时钟每秒只“滴答”50 或 100 次。所以差值的小数位多,不代表精度就有那么高。
如果同一段操作量了多次,各次结果不一致是正常的,不要取其中最小的那个当成“真实耗时”。
适用限制与参考资料
适用范围:本文只处理用 perf_counter 和 time() 的差值测量一段自建操作的耗时,以及两者的用途区别。所有示例都是自建的练习代码,不涉及真实业务数据,也不执行任何系统修改。
几条需要提前知道的边界:
- 文档说明,这个模块的函数并非在所有平台上都可用,多数函数调用的是同名平台 C 库函数,语义可能因平台而异。
- 本文不给出任何性能基准、耗时标准或“多快算快”的判断,示例中的循环次数和打印结果都不是基准结论。
- 本文不涉及多线程、多进程计时,也不涉及 clock_gettime 等底层接口。
- 计时结果受机器负载、解释器版本等因素影响,本文不对具体数值做解释。
参考资料:Python 官方 time 模块文档,https://docs.python.org/3/library/time.html
观看知识要点视频 18 秒
18秒无旁白要点导览,文字来自已审核正文;完整步骤、条件及参考资料见下方。
参考资料
以下原始资料提供本文依据;请结合日期、适用条件和产品说明查阅。
请结合原始资料的适用条件阅读。
返回效率工具 →