3. 基准测试(Baseline)建立:如何选择基准版本、基准场景设计、基准数据采集方法

做性能回归对比,最怕什么?

怕你测了半天,发现数据根本没法比。

我见过太多团队,上来就对比两个版本的吞吐量,结果发现基准版本选错了,场景设计也不对,最后折腾两周得出一个结论——「好像新版本快了一点?」。这种结论,说白了跟没测一样。

所以今天咱们聊聊基准测试怎么建。这是整个回归对比的根基,根基不稳,后面全是白费。

3.1 基准版本怎么选?

选基准版本,不是随便挑一个稳定版就完事了。我个人习惯遵循三个原则:

  1. 选「公认稳定」的版本——不是你觉得稳定,而是线上跑了至少一个月没出大问题的版本。
  2. 选「功能完整」的版本——如果基准版本本身就有性能缺陷,那对比出来的「优化」其实是修复 Bug 的假象。
  3. 选「可复现」的版本——这个版本必须能随时部署、随时跑起来。我遇到过有人拿半年前的 Docker 镜像当基准,结果镜像都找不到了,你说尴尬不尴尬。

我的建议:

如果项目有里程碑版本(比如 v2.0.0、v3.1.0),优先选这些。如果没有,选最近一次线上稳定部署的版本。

千万别选「开发中的最新版」当基准——那玩意儿可能今天跑 100ms,明天就崩了。

一个小技巧:

基准版本确定后,打一个 Git Tag,比如 baseline-v1。这样以后谁想复现,直接 checkout 就行。

3.2 基准场景怎么设计?

场景设计,是基准测试里最容易翻车的地方。

你想想看,如果你只测了一个「用户登录」接口,然后说系统性能提升了 20%。结果上线后发现,真正的瓶颈在「订单查询」接口——那你这 20% 有什么意义?

我一般把场景分成三类:

场景类型 说明 举例
核心路径场景 用户最常走的流程 登录、搜索、下单
边界压力场景 极限情况下的表现 并发 1000、数据量 1 亿
异常恢复场景 系统出问题后的恢复能力 DB 宕机后重启、缓存穿透

嗯,这里要注意:核心路径场景必须覆盖线上流量的 80% 以上。怎么知道哪些是核心路径?看监控,看日志,看调用链。别猜,猜出来的场景十有八九是错的。

我曾经踩过的坑:

有一次我设计场景时,只测了「读接口」,没测「写接口」。结果新版本上线后,读性能提升了 30%,但写性能下降了 50%。用户反馈说「保存按钮点半天没反应」——嗯,从那以后我再也不敢只测读不测写了。

3.3 基准数据怎么采集?

数据采集,说白了就是「怎么把性能数据变成可对比的数字」。

我常用的采集方法有四种:

  • 日志埋点——在关键代码路径上加耗时日志。简单粗暴,但容易漏。
  • APM 工具——比如 SkyWalking、Pinpoint。能自动采集调用链数据,但部署成本高。
  • 压测工具——比如 JMeter、wrk。适合模拟高并发场景,但需要写脚本。
  • 系统监控——比如 Prometheus + Grafana。采集 CPU、内存、IO 等指标,适合看整体趋势。

我个人习惯是:压测工具 + APM 工具搭配使用。压测工具负责「制造压力」,APM 工具负责「记录细节」。

举个例子,用 wrk 压测一个 HTTP 接口:

wrk -t12 -c400 -d30s http://localhost:8080/api/order/list

这条命令的意思是:12 个线程,400 个并发连接,持续压 30 秒。跑完后会输出延迟分布、吞吐量等数据。

但光有 wrk 的数据还不够。我还会配合 APM 工具,看每个接口内部的耗时分布——比如数据库查询花了多少时间,Redis 缓存命中率怎么样。这样你才知道「慢在哪里」。

数据采集的三个关键点:

  1. 采集多次,取中位数——别只跑一次就下结论。网络抖动、GC 停顿都会影响单次结果。我一般跑 5 次,取 P50 或 P99。
  2. 记录环境信息——CPU 型号、内存大小、JVM 参数、操作系统版本。这些不记,以后想复现都难。
  3. 数据要可导出——别把数据只存在某个工具的界面上。导出成 CSV 或 JSON,方便后续做对比分析。

3.4 基准测试的整体流程

说了这么多,咱们用一张图把整个流程串起来:

基准测试建立流程 选择基准版本 设计基准场景 采集基准数据 数据归档与标记 后续回归对比 打 Tag、记录版本号 核心路径 + 边界场景 多次采集、记录环境 数据导出、打标签 基于基准做对比 虚线表示:基准数据可被后续回归对比反复使用

这张图其实就说明了一件事:基准测试不是一次性的,它是后续所有回归对比的锚点。你每次做性能对比,都要回到这个基准上来。

我的习惯:

每次基准测试完成后,我会把数据归档到一个固定的目录,命名规则是 baseline_{版本号}_{日期}.csv。这样半年后回来找,也能一眼找到。

3.5 避坑指南

最后,分享几个我亲身踩过的坑:

  • 「基准版本」和「对比版本」的环境不一致——比如基准版本跑在 4 核机器上,对比版本跑在 8 核机器上。这种对比毫无意义。
  • 只测一次就下结论——我见过有人跑一次压测,看到延迟低了 10ms,就兴冲冲地说「优化成功」。结果第二天再跑,发现又回去了。为什么?因为第一次跑的时候 JVM 还没预热。
  • 忽略冷启动和预热——很多系统刚启动时性能很差,跑几分钟后才稳定。基准测试一定要等系统「热起来」再采集数据。

我曾经犯过的错:

有一次我拿新版本和基准版本对比,发现新版本快了 50%。我高兴坏了,赶紧准备上线。结果同事提醒我:「你基准版本的数据是上周采集的,这周线上流量翻了一倍,数据早就变了。」——嗯,从那以后我每次做对比前,都会重新跑一遍基准测试,确保数据是「新鲜的」。

好了,基准测试的建立就聊到这儿。记住一句话:基准测试不是用来证明「新版本有多好」的,而是用来确保「你不会变得更差」的。

可可精品资料库