第3章:性能基准测试

聊到性能调优,我第一个想跟你聊的,就是基准测试。

很多人一上来就搞优化,改配置、调参数、换框架……忙活半天,结果呢?
性能到底是变好了还是变差了?说不清楚。
这就是典型的「没有基准,就没有真相」。

基准测试,说白了就是给你的系统拍一张「体检照」。
你优化前拍一张,优化后再拍一张。两张一对比,效果一目了然。

什么是基准测试

基准测试(Benchmarking),是一种标准化的测试方法。
它的核心目的只有一个:在可控条件下,测量系统的性能指标。

我习惯把它分成两类:

  • 微基准测试:针对一小段代码,比如一个算法、一个函数。测的是纳秒、微秒级别。
  • 宏基准测试:针对整个系统,比如一个Web服务、一个数据库。测的是吞吐量、延迟。

你想想看,如果你连系统「正常时」的性能数据都没有,你怎么判断它「异常时」到底差了多少?
嗯,这就是基准测试存在的意义。

核心观点:没有基线,就没有优化。基准测试是性能调优的「第一块基石」。

基准测试的设计原则

我在项目中踩过不少坑。有一次,我测了一个接口的QPS,结果数据忽高忽低,完全没法用。
后来才发现,测试机器上跑着别的任务,CPU被抢了。
所以,设计基准测试时,有几个原则你必须记住:

  1. 可重复性:同样的条件,跑十次,结果应该差不多。如果波动大,说明环境没控制好。
  2. 隔离性:被测系统尽量独占资源。别一边跑测试,一边开浏览器看视频。
  3. 代表性:测试场景要贴近真实。别拿「Hello World」去压测一个电商系统。
  4. 可度量性:指标要明确。是测TPS?还是P99延迟?先想清楚。
  5. 预热期:很多系统有JIT编译、缓存填充。刚启动就测,数据不准。我一般会先跑几分钟「热身」。

我的小习惯:每次做基准测试,我都会记录下环境信息——CPU型号、内存大小、JVM参数、操作系统版本。这些细节,往往就是排查问题的关键线索。

常用基准测试工具

工具不在多,在于会用。我挑几个最常用的跟你聊聊。

JMH(Java Microbenchmark Harness)

如果你写Java,JMH是微基准测试的「标配」。
它由JVM专家开发,专门解决JVM预热、编译器优化、死代码消除等问题。

举个例子,你想比较两种字符串拼接方式的性能:

@Benchmark
public void testStringConcat() {
    String s = "";
    for (int i = 0; i < 1000; i++) {
        s += i;
    }
}

@Benchmark
public void testStringBuilder() {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < 1000; i++) {
        sb.append(i);
    }
}

跑完之后,JMH会告诉你:哪个方法更快,快了多少,置信区间是多少。
我曾经用JMH发现过一个诡异的性能问题——某个工具类的加锁方式不对,导致高并发下性能暴跌。没有JMH,这种问题很难定位。

wrk 和 ab

这两个是HTTP压测工具,用来测Web服务的吞吐量。

  • ab(Apache Bench):老牌工具,简单直接。适合快速压测。
  • wrk:新一代工具,支持Lua脚本,能模拟复杂场景。我个人更推荐wrk。

用wrk压测一个接口:

wrk -t12 -c400 -d30s http://localhost:8080/api/test

这条命令的意思是:用12个线程,保持400个并发连接,持续压30秒。
输出结果会告诉你:总请求数、每秒请求数(RPS)、延迟分布。

注意:压测时,别把目标机器压挂了。我曾经有一次压测太猛,直接把测试环境的数据库打崩了……嗯,从那以后,我每次压测都会先设一个「安全阈值」。

sysbench

sysbench是数据库和系统层面的基准测试工具。它支持CPU、内存、磁盘I/O、数据库(MySQL、PostgreSQL)等。

比如,测一下数据库的OLTP性能:

sysbench --db-driver=mysql --mysql-user=root --mysql-password=123456 \
         --mysql-db=test --table-size=1000000 oltp_read_write run

它会生成一张大表,然后模拟读写操作,最后输出TPS、延迟、95%延迟等指标。

我习惯用sysbench做数据库的「基准快照」。每次数据库升级或参数调整后,跑一遍sysbench,对比数据,心里就有底了。

如何建立性能基线

建立性能基线,不是跑一次测试就完事了。它是一个持续的过程。

我的做法是这样的:

  1. 确定关键指标:比如TPS、P99延迟、CPU使用率、内存占用。别贪多,3-5个核心指标就够了。
  2. 固定测试环境:硬件、软件、网络、数据量,全部固定下来。每次测试都用同一套环境。
  3. 多次运行取均值:至少跑5次,去掉最高最低,取平均值。这样可以消除偶然波动。
  4. 记录上下文:把测试时间、代码版本、配置参数、环境信息都记录下来。方便以后回溯。
  5. 自动化执行:把基准测试集成到CI/CD流水线中。每次代码提交,自动跑一遍基线测试。如果性能下降超过阈值,立刻告警。

一句话总结:性能基线,就是你的「性能账本」。每次优化,都是在跟这个账本做对比。

本章知识体系

下面这张图,帮你梳理了本章的核心逻辑:

性能基准测试知识体系 基准测试 什么是基准测试 微基准 / 宏基准 设计原则 可重复 / 隔离 / 代表 / 可度量 / 预热 常用工具 JMH / wrk / ab / sysbench 建立性能基线 指标 / 环境 / 多次运行 / 记录 / 自动化 核心:没有基线,就没有优化

基准测试,是性能调优的起点。没有它,你所有的优化都是「盲人摸象」。
我建议你,从今天开始,给每个系统都建立一份性能基线。哪怕只是一个简单的压测脚本,也比「凭感觉」强一百倍。

最后一个小建议:基准测试的结果,一定要可视化。用折线图展示TPS趋势,用热力图展示延迟分布。数据一上图表,问题就藏不住了。

可可精品资料库