P95 从 120 毫秒变 400 毫秒,功能测试全绿也测不出来——这类退化只能靠跟自己的历史比。
这次改动后,基准负载下的 P95 与上一次相比变化了多少毫秒?
答不出数字,说明没有基线。先按固定负载模型跑一次并存档——第一次压测只做存档,不设通过与否;有了基线,第二次才谈退化。
「感觉挺快」不是判据,带负载条件的数字才算。先把负载条件写死——并发数、数据量、请求分布、机器规格、预热多久后统计多久——再让脚本按它跑;条件一变,前后两次的数字就没有可比性。
前置条件写在一起:上面这几个数对应单实例、2 核 4G、数据库同机的前提,前提变了整套数都要重跑。它不进三类判断里的任何一类——别的检查判对错,它判变化。
一份性能报告是「负载条件 + 几个百分位 + 跟上次的差」。它判的是变化,不是对错。
提交 a1b2c3d 单实例 2C4G 并发 50 预热 60s / 统计 300s P95 287ms(上次 241ms,+19%) P99 742ms 吞吐 214rps 错误率 0.1% 结论:达标;本次让 P95 变差 19%
要认的是这个形状:负载条件与提交号写在报告里,结论写明让哪一项变差了多少。只写「有优化」等于没写。
提交 a1b2c3d 单实例 2C4G 并发 10(上次 50)
预热 10s / 统计 60s(上次 300s)
P95 132ms(上次 241ms,-45%)
结论:达标;本次优化 45%
认它的办法:负载条件变了,数字就不可比。并发、统计时长、实例规格任何一项与上次不同,这份报告等于没跑。把上一次的数字删掉只留本次,同样是这个效果——没有基线就没有趋势。
场景:助手给列表接口加了一个联表字段。接口测试全绿,功能没问题,改动合并了。
每次压测至少十几分钟,算不进日常门禁,所以只在改到那几类地方时跑;压错一次会浪费半天,还会得出一个不能用的结论。
| 情况 | 跑不跑 | 为什么 |
|---|---|---|
| 改了查询或数据访问路径 | 跑 | 这一类退化最隐蔽,功能测试看不出来 |
| 新增了循环里的远程调用 | 跑 | 循环里查库、发请求、读文件都会改变延迟分布 |
| 改了缓存或批量策略 | 跑 | 失效范围与批量大小直接影响百分位 |
| 要上线了 | 跑 | 在接近生产的配置下跑一次,结果附进发布记录;没跑就写「未压」 |
| 功能测试还没绿 | 不跑 | 压的是一个会出错的行为,百分位没有意义 |
| 还没定判据,想先跑一遍看看 | 不跑 | 看到数字之后再定标准,标准一定会被数字迁就 |
| 在开发机或共享机器上压 | 不跑 | 数字既不可比也不可复现,同机服务还会被拖慢 |
| 数据集只有手搓的几十行 | 不跑 | 压不出循环查询与全表扫描,那是数据量到了才现形的问题 |
容量估算回答的是另一个问题:「要几台、留多少余量」。它按压测得出的单实例能力推算,前提(峰值、单条大小、日增量)写进同一份文档;前提变了就重算并替换,不留两套数字。不达标就调低阈值,属于改判据,要走单独的合并请求。
负载模型与阈值写进压测脚本,不写在报告里靠人看;结果落盘进仓库,下一次才有比较对象。每次运行要留下三个百分位、吞吐、错误率、当时的提交号与环境规格——缺一样,这个数字就不能引用。门禁里只保留一条硬检查:相对上次退化超过 20% 即失败。