应使用 time.perf_counter() 而非 time.time() 测量耗时,因其单调、高精度、不受系统时间调整影响;关键路径需重复测量取最小值或中位数;优先用 timeit 模块做基准测试;多线程/异步场景需结合 process_time 或事件循环时间分析真实开销。

用 time.perf_counter() 而不是 time.time()
time.time() 返回的是系统时钟时间,受系统时间调整(如 NTP 同步、手动修改)影响,可能跳变或倒退,不适合测耗时。time.perf_counter() 是单调递增的高精度计时器,专为测量间隔设计,分辨率通常达纳秒级,且不受系统时钟干扰。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 始终优先用
time.perf_counter(),尤其在需要亚毫秒级精度或长时间运行的场景 - 避免混用
perf_counter()和process_time()—— 后者只统计 CPU 时间,会忽略 sleep 或 I/O 等等待时间 - 两次调用必须在同一进程内,跨线程也安全,但跨进程需另做同步
注意函数调用开销和重复测量的必要性
单次测量容易受调度抖动、缓存预热、JIT 编译等干扰,结果波动大。比如一个简单 sum(range(1000)) 测一次可能是 0.0002s,下一次可能 0.0008s。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 对关键路径至少重复运行 3–5 次,取最小值(排除干扰),或取中位数(更稳健)
- 若要排除 Python 解释器启动/导入开销,把待测代码封装成函数,先 warm up 一次再正式计时
- 避免在计时块内做 print、日志等 I/O 操作——它们本身耗时不稳定,会污染结果
用 timeit 模块做轻量基准测试
手动写 perf_counter() 套壳适合嵌入逻辑,但做纯函数性能对比时,timeit 更可靠:它自动禁用 GC、重复执行、剥离 setup 开销。
创建 Flask + Vue.js 全栈项目,采用单端口架构、uv 依赖管理、结构化日志和生产级前端设计。当用户要求以下操作时触发:创建新的 Flask+Vue 项目、搭建 Web 应用、构建全栈 Python+Vue 应用、初始化 Flask Web 项目、设置单端口 Flask 前后端项目。触发词:新建项目、创建项目、搭建项目、Flask项目、Vue项目。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 命令行快速比对:
python -m timeit -s "import math" "math.sqrt(12345)" - 在脚本中用
timeit.timeit(),注意number=1000000控制执行次数,避免单次太短导致误差放大 - 不要传字符串形式的 setup 代码给
timeit.timeit(stmt, setup=...),除非你明确需要动态执行;否则直接用lambda或函数引用更清晰
多线程/异步环境下不能只靠 perf_counter()
在 asyncio 或多线程中,perf_counter() 仍有效,但它测的是 wall-clock 时间,无法区分是 CPU 占用还是等待资源。比如 await asyncio.sleep(0.1) 会如实计入耗时,但这不是“计算开销”。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 测异步函数真实 CPU 负担,应结合
time.process_time()(但注意它不包含 async wait) - 想定位协程阻塞点,用
asyncio.get_event_loop().time()替代,它返回事件循环内部单调时间,与perf_counter()对齐但更贴近调度视角 - 生产环境长期监控耗时,别依赖单次
perf_counter()差值——要用采样 + 分位数聚合(如 p95/p99),否则平均值毫无意义
真正难的不是怎么记时间,而是判断该记哪一段、在哪种上下文里记、以及如何解释那个数字背后的真实含义。

















