pytest-benchmark 是最轻量的性能回归测试工具,通过 @pytest.mark.benchmark 装饰器在现有功能测试中监控关键路径耗时,需配合 --benchmark-only 或 --benchmark-compare 运行并对比历史 json 数据。

怎么用 pytest-benchmark 做最小可行回归测试
性能回归测试不等于压测,核心是同一份代码在不同版本间跑相同基准,看关键路径耗时有没有异常上涨。用 pytest-benchmark 是最轻量的选择,它不改原有测试结构,只加一个装饰器就能捕获耗时。
实操建议:
- 在已有功能测试里,对需要监控的函数加
@pytest.mark.benchmark,不是新建一堆 benchmark 专用测试文件 - 运行时必须加
--benchmark-only或--benchmark-compare,否则benchmark标记会被忽略 - 对比历史数据要靠
--benchmark-compare=0001(数字是之前生成的 JSON 文件编号),不能靠肉眼记时间 - 默认每次跑 25 轮取中位数,如果函数本身极快(min_time 和
min_rounds,否则统计抖动大
timeit 和 perf_counter 在回归测试里别混用
写临时脚本快速比对可以,但进 CI 就容易翻车。根本问题是精度和上下文不可控:timeit 默认关 GC、清缓存,而真实服务里 GC 是开着的;perf_counter 只是单次计时,没做多次采样和离群值剔除。
常见错误现象:
立即学习“Python免费学习笔记(深入)”;
- 本地用
timeit.timeit(..., number=10000)测出 A 比 B 快 5%,CI 上跑出来相反——因为没锁频、没绑核、没关 turbo boost - 用
perf_counter包一层函数就提交,结果某次 CI 被调度器切走 20ms,整条 baseline 崩掉
正确做法:回归测试只依赖 pytest-benchmark 的内置逻辑,它会自动做 warmup、剔除前 2 轮、用 IQR 判定离群值。自己手写计时器等于绕过所有防抖机制。
经过一段时间的开发,以及内部测试,同程网联盟景区新版程序正式发布推出,感谢广大联盟会员一直以来的支持与关注! 同程网联盟景区新版程序新功能介绍:1.统一的页面风格。页面风格将与随后推出的度假线路、酒店、机票以及融合版联盟程序风格保持一直;2.新增后台管理系统。可更加方便快捷的对网站进行个性化设置;3.动态与伪静态切换。后台操作,简单便捷;4.缓存管理。新增缓存,提高网站访问速度,后台可定期清理;5
CI 中跑性能回归必须固定硬件与 Python 环境
同一份 benchmark 结果在 M2 Mac 和 Intel Xeon 上没法直接比,Python 小版本升级(比如 3.11 → 3.12)也可能让 dict 操作快 8%,这不是代码问题,是解释器优化。
所以:
- CI 镜像必须指定完整 Python 版本,例如
python:3.11-slim-bookworm,不能只写python:3.11 - 禁止在 GitHub Actions / GitLab CI 上用
ubuntu-latest,得固定为ubuntu-22.04,避免底层内核/调度器升级干扰 - 如果团队有自建 runner,要在机器上跑
lscpu | grep 'Model name\|MHz'并写进 benchmark 报告头,不然下次换机器连 baseline 都对不上
怎么设性能阈值才不会天天收告警邮件
设成“上涨超过 5% 就失败”看着合理,实际非常脆弱。小波动、CPU 抢占、磁盘缓存未热都会触发误报。
更靠谱的做法:
- 先跑 3–5 次基线,用
--benchmark-autosave存档,再从这些数据里算标准差,把阈值设成mean + 2 * std - 对 IO 密集型函数(比如读配置、查 DB),阈值放宽到 15%~20%,这类操作受外部影响太大
- 用
--benchmark-histogram输出分布图,如果某次结果明显右偏(长尾变长),比均值上涨更重要——说明偶发卡顿变多了 - CI 失败后别只看百分比,先检查
benchmark.json里的stats.outliers字段,确认是不是真有离群慢请求
真正难的不是跑出数字,是让每次跑出来的数字可比。环境、工具链、统计口径,漏掉任何一环,回归测试就变成定时制造噪音。










