4、性能回归对比工具:JMeter对比模式、wrk与ab的对比用法、Locust的对比测试

性能回归对比,说白了就是「改完代码,系统变快还是变慢了?」。这个问题,我几乎每次上线前都要问自己一遍。

你可能会想,跑一遍压测不就行了?嗯,没那么简单。环境波动、网络抖动、GC停顿……这些干扰因素会让单次结果很不靠谱。所以我们需要专门的对比工具和方法。

今天我就聊聊我常用的四类工具:JMeter、wrk、ab 和 Locust。它们各有脾气,也各有妙用。

4.1 JMeter 对比模式:别只跑一次

JMeter 大家都很熟,但很多人拿它做对比测试时,犯过一个低级错误——只跑一轮就下结论。

我个人习惯的做法是:至少跑 3 轮,取中位数。为什么不是平均值?因为平均值容易被极端值带偏。中位数更稳。

具体操作上,JMeter 提供了两种对比思路:

  • 命令行非 GUI 模式:用 -n -t 参数跑,结果存成 jtl 文件。然后对比两次的 jtl 文件。
  • 使用 Comparison Report:JMeter 5.0 之后有个插件叫「Comparison Report」,可以直接把两次结果叠在一起看。

我举个例子。假设你要对比优化前后的接口延迟:

# 优化前
jmeter -n -t test_plan.jmx -l before.jtl

# 优化后
jmeter -n -t test_plan.jmx -l after.jtl

# 然后用 Comparison Report 插件加载两个 jtl 文件
我的小技巧:跑对比测试时,尽量保持线程数、循环次数、Ramp-Up 时间完全一致。我见过有人改了线程数还跑来对比,结果当然不准。

JMeter 的对比报告会给出每个百分位的延迟变化。我重点关注 P99 和 P999。这两个值最能反映系统的「长尾」问题。

举个例子,有一次我优化了一个缓存逻辑,平均延迟从 50ms 降到了 30ms,但 P99 反而从 200ms 涨到了 500ms。这就是典型的「平均好看了,但尾巴更长了」。如果只看平均值,你就会被骗。

4.2 wrk 与 ab:轻量级对比利器

wrk 和 ab 都是命令行工具,适合快速验证。它们不像 JMeter 那么重,但胜在简单直接。

ab(Apache Bench) 是最老牌的压测工具。它的用法很简单:

ab -n 10000 -c 100 http://your-api.com/endpoint

但 ab 有个硬伤——它只支持 HTTP/1.0,而且不支持 Keep-Alive 的复用。这意味着它的结果往往比实际偏慢。我一般只用它做「快速冒烟测试」,不会拿它做精细对比。

wrk 就好多了。它支持 HTTP/1.1,还能用 Lua 脚本定制请求。我个人更偏爱 wrk。

wrk -t12 -c400 -d30s http://your-api.com/endpoint

这个命令的意思是:12 个线程,400 个并发连接,持续 30 秒。

wrk 的输出里,我最关注的是 Requests/sec 和 Latency 的分布。特别是 Std Dev(标准差),如果这个值很大,说明系统不稳定。

对比测试的关键:用 wrk 做对比时,一定要保证 -t(线程数)和 -c(连接数)完全一致。我曾经犯过一个错,优化前用 -t4 -c100,优化后用了 -t8 -c100,结果吞吐量翻倍了,我还以为是优化有效……后来才发现是线程数变了。

我整理了一个对比表,方便你快速选择:

工具 协议支持 并发模型 适合场景 我的评价
ab HTTP/1.0 单线程 快速冒烟 够用,但别太信它
wrk HTTP/1.1 多线程 + epoll 精细对比 我的首选
JMeter HTTP/1.1 + 自定义 线程池 复杂场景 功能最强,但重
Locust HTTP/1.1 + 自定义 协程(gevent) 脚本化对比 灵活,但学习成本高

4.3 Locust 的对比测试:用代码控制一切

Locust 跟前面几个工具不太一样。它用 Python 写测试脚本,可以精确控制每个用户的行为。对于复杂的业务场景,比如「先登录、再下单、再支付」,Locust 就比 wrk 和 ab 强太多了。

做对比测试时,Locust 的 Web UI 可以实时看到两个版本的曲线。但我个人更习惯用 无头模式(headless),然后对比 CSV 报告。

# 优化前
locust -f locustfile.py --headless -u 100 -r 10 --run-time 5m --csv=before

# 优化后
locust -f locustfile.py --headless -u 100 -r 10 --run-time 5m --csv=after

然后我会写一个简单的 Python 脚本,把 before_stats.csv 和 after_stats.csv 里的关键指标拉出来对比。

注意:Locust 的默认统计是「每秒采样一次」。如果你的测试时间太短(比如 30 秒),样本量不够,对比结果可能不靠谱。我建议至少跑 3 分钟以上。

Locust 还有一个好处:你可以用 @task 装饰器定义不同权重的任务。比如 70% 的请求是查询,30% 是写入。这样对比出来的结果更贴近真实业务。

我曾经在一个项目中,用 Locust 对比了「同步写入」和「异步写入」两种方案。同步方案的平均延迟是 120ms,异步方案是 15ms。但异步方案在 P99 上偶尔会飙到 2 秒。这就是典型的「异步换吞吐,但牺牲了稳定性」。如果没有 Locust 的精细对比,我可能就盲目上线了。

4.4 核心逻辑:对比测试的流程

说了这么多工具,其实对比测试的核心逻辑就三步:

  1. 基线建立:在「优化前」跑一轮,记录所有关键指标。
  2. 变量控制:只改你要验证的那个变量(比如代码、配置、硬件),其他全部保持不变。
  3. 结果对比:用同一个工具、同一个脚本、同一个环境,跑第二轮,然后对比。

下面这张图是我自己总结的对比测试流程,你可以参考:

1. 建立基线 优化前跑一轮 2. 变量控制 只改一个变量 3. 结果对比 优化后跑第二轮 结论 关键指标对比清单: • 吞吐量(Requests/sec)—— 系统处理能力 • 平均延迟(Avg Latency)—— 用户体验 • P99 / P999 延迟 —— 长尾问题 • 错误率(Error Rate)—— 稳定性 • 标准差(Std Dev)—— 波动程度 ⚠ 避坑:不要只看平均值!P99 和错误率同样重要。

嗯,这张图基本概括了我做对比测试的整个思路。你照着这个流程走,基本不会出大问题。

我的经验:对比测试最怕「环境不一致」。比如优化前是周一早上跑的,优化后是周五下午跑的——这两个时间段的服务器负载完全不同。我建议:两次测试尽量在同一个时间段、同一台机器上跑。如果条件允许,用 CI/CD 流水线自动触发对比测试,这样最靠谱。

最后说一句:工具只是手段,对比的逻辑才是核心。不管你用 JMeter、wrk、ab 还是 Locust,只要控制好变量、跑够样本、关注 P99,你就能得到可信的结论。

想要更多资料,联系可可