2. 性能基准测试:基准测试的意义、常用工具与场景设计
性能优化这件事,最怕的就是「凭感觉」。
你觉得自己优化了代码,系统应该快了 30%。结果上线后,业务方说没感觉。你说你优化了数据库,QPS 翻了一倍。结果运维说,CPU 反而更高了。
为什么会这样?因为没有基准。
基准测试,说白了就是给系统拍一张「体检 X 光片」。你得先知道它现在什么水平,才能判断你改完以后到底是进步了还是退步了。我见过太多团队,优化做了一堆,最后连个对比数据都拿不出来——那叫瞎忙活。
2.1 基准测试到底在测什么
基准测试不是压力测试,也不是功能测试。它的核心目标只有一个:在可控条件下,测量系统的某项性能指标。
我个人习惯把基准测试分成两类:
- 微基准测试:针对单一组件或单一操作。比如「Redis 的 SET 命令每秒能跑多少次」、「MySQL 在 16 并发下的简单查询延迟」。
- 宏基准测试:模拟真实业务场景。比如「模拟 1000 个用户同时浏览商品详情页,系统的吞吐量和响应时间」。
你想想看,如果你连微基准都没跑明白,就直接上宏基准,出了问题你根本不知道是网络瓶颈、磁盘瓶颈还是代码瓶颈。所以我的建议是:先微后宏,分层测试。
核心原则:基准测试不是为了证明系统有多快,而是为了建立一个可重复、可对比的「性能基线」。
2.2 常用工具:三把手术刀
工具不在多,在于会用。我这些年折腾下来,真正高频使用的基准测试工具就三个:sysbench、fio、iperf。它们分别对应 CPU/内存/数据库、磁盘 IO、网络带宽。
2.2.1 sysbench:CPU、内存、数据库一把抓
sysbench 是我用得最多的工具。它支持 CPU、内存、互斥锁、线程、甚至 MySQL 和 PostgreSQL 的基准测试。
先看一个最简单的 CPU 基准测试:
# 测试 CPU 素数计算性能,4 个线程跑 30 秒
sysbench cpu --threads=4 --time=30 run
输出里你会看到 events per second(每秒事件数)。这个值越高,说明 CPU 的计算能力越强。我在项目中遇到过一个问题:两台服务器 CPU 型号一样,但一台跑出来的 events 比另一台低了 20%。查了半天,发现是 BIOS 里关了超线程。嗯,这就是基准测试的价值——它能帮你发现「看起来一样,实际上不一样」的硬件差异。
再看内存测试:
# 测试内存顺序读写,总数据量 10GB
sysbench memory --memory-block-size=1M --memory-total-size=10G run
这里要注意,--memory-block-size 会影响结果。块越小,越考验内存延迟;块越大,越考验内存带宽。我一般会跑两个尺寸:4K 和 1M,分别看延迟和带宽。
数据库测试是 sysbench 的重头戏。以 MySQL 为例:
# 准备数据
sysbench oltp_read_write --table-size=1000000 --mysql-host=127.0.0.1 --mysql-user=root --mysql-password=yourpass prepare
# 运行测试,16 个线程跑 60 秒
sysbench oltp_read_write --threads=16 --time=60 --mysql-host=127.0.0.1 --mysql-user=root --mysql-password=yourpass run
# 清理
sysbench oltp_read_write cleanup
输出里的 tps(每秒事务数)和 qps(每秒查询数)是核心指标。我习惯把结果记录到表格里,方便对比不同参数下的表现。
2.2.2 fio:磁盘性能的照妖镜
磁盘性能是系统性能的常见瓶颈。fio 是业界标准,没有之一。
先看一个典型的随机读写测试:
# 4K 随机读,队列深度 32,直接 IO,测试 60 秒
fio --name=randread --ioengine=libaio --iodepth=32 --rw=randread --bs=4k --direct=1 --size=1G --numjobs=1 --runtime=60 --group_reporting
关键参数解释:
| 参数 | 含义 | 我的建议 |
|---|---|---|
--rw |
读写模式(randread/randwrite/read/write/rw) | 至少跑 randread 和 randwrite |
--bs |
块大小 | 4K 模拟数据库,1M 模拟大文件 |
--iodepth |
IO 队列深度 | NVMe 盘可以到 64,SATA SSD 建议 32 |
--direct=1 |
绕过文件系统缓存 | 必须开,否则测的是缓存不是磁盘 |
我曾经踩过的坑:用 fio 测试时没加 --direct=1,结果 IOPS 跑到了 50 万,高兴了半天。后来发现数据全在 Page Cache 里,根本没落到磁盘上。加了 --direct=1 之后,真实 IOPS 只有 8 万。所以记住:测磁盘,一定要绕过缓存。
2.2.3 iperf:网络带宽的试金石
网络问题往往最隐蔽。iperf 可以帮你快速确认两台机器之间的实际带宽。
服务端:
iperf3 -s
客户端:
iperf3 -c 192.168.1.100 -t 30 -P 4
-P 4 表示 4 个并行流。我一般会跑三次:单流、多流、反向流。为什么?因为很多网络瓶颈只在多流或反向传输时才暴露出来。比如有一次,客户说两台服务器之间带宽只有 200Mbps,但网卡明明是万兆的。我用 iperf 一测,单流确实只有 200Mbps,但 4 个并行流能跑到 9.2Gbps。最后发现是 TCP 窗口大小没调,单流被限制了。
2.3 如何设计基准测试场景
工具学会了,但场景设计才是真正的功夫。我见过有人拿着 sysbench 默认参数跑一遍,然后说「我的数据库性能很好」——这其实没什么意义。因为你跑的默认场景,跟你的业务场景可能完全不搭。
设计基准测试场景,我总结了四个步骤:
- 明确被测对象和指标:你要测什么?CPU、内存、磁盘、网络还是数据库?指标是什么?TPS、延迟、带宽还是 IOPS?
- 确定负载模型:你的业务是读多写少还是写多读少?是顺序访问还是随机访问?峰值并发是多少?
- 设置测试参数:线程数、数据量、运行时长、队列深度。这些参数要尽量贴近生产环境。
- 执行并记录基线:至少跑 3 次,取中位数或平均值。记录所有环境信息(内核版本、硬件配置、驱动版本)。
举个例子。假设你要为 MySQL 做基准测试:
- 指标:TPS 和 P99 延迟
- 负载模型:70% 读、30% 写,数据量 1000 万行
- 参数:并发从 1 开始,逐步增加到 128,每次跑 5 分钟
- 基线:记录默认配置下的 TPS 和延迟曲线
这样你后续做任何优化——调整 buffer pool、修改刷盘策略、升级硬件——都能拿这个基线来对比。没有基线,优化就是盲人摸象。
2.4 知识体系:基准测试全景图
下面这张图是我自己整理的基准测试知识体系,你可以把它当作一个检查清单。每次做基准测试前,对着这张图过一遍,基本不会漏东西。
2.5 避坑指南与最佳实践
最后,分享几个我这些年总结出来的经验。每一个都是用真金白银换来的教训。
每次测试前,先确认系统状态:用 top、iostat、free -h 看一眼。确保没有其他进程在抢资源。我曾经在跑 sysbench 的时候,后台正好在跑 crontab 备份任务,结果数据全废了。
多次运行,取中位数:单次测试结果不可信。我一般跑 5 次,去掉最高和最低,取中间 3 次的平均值。如果波动超过 10%,说明环境不稳定,先排查问题再继续。
记录一切:内核版本、驱动版本、BIOS 设置、文件系统类型、挂载参数、甚至室温。你永远不知道哪个细节会影响结果。有一次我对比两次测试数据,发现磁盘 IOPS 差了 15%,查了两天,最后发现是第一次测试时磁盘的固件版本不同。从那以后,我每次测试前都会用 dmesg | grep -i firmware 看一眼。
基准测试不是一次性工作。它应该成为你日常运维的一部分。每次系统变更——升级内核、调整参数、更换硬件——都跑一遍基准测试,把结果记录下来。时间长了,你手里就有一份完整的性能基线库。到那时候,任何性能问题在你面前都藏不住。