性能基准:网络性能指标定义与基准测试方法论
做网络性能分析,第一件事是什么?不是抓包,不是看代码,而是先搞清楚——你到底要测什么。我见过太多人上来就跑 iperf3,看着屏幕上的数字觉得"还行",结果上线一压就崩。说白了,你连指标都没对齐,后面的分析全是空中楼阁。
这一章,我们就来把网络性能的四个核心指标掰开揉碎,再聊聊怎么用 iperf3 和 netperf 做靠谱的基准测试。嗯,都是我在项目中踩过坑之后总结出来的经验。
1. 四个核心指标:吞吐量、延迟、PPS、连接数
网络性能不是"快不快"这么简单。你得从四个维度去看,缺一个都不完整。
| 指标 | 定义 | 单位 | 典型场景 |
|---|---|---|---|
| 吞吐量 | 单位时间内成功传输的数据量 | bps / MB/s | 大文件传输、视频流 |
| 延迟 | 数据从发送端到接收端的单向耗时 | ms / μs | 实时通信、交易系统 |
| PPS | 每秒处理的数据包数量 | packets/s | 网关、防火墙、负载均衡 |
| 连接数 | 系统同时维持的 TCP 连接数量 | 个 | Web 服务器、数据库连接池 |
关键认知:这四个指标之间是相互制约的。高吞吐量不一定意味着低延迟,高 PPS 处理能力也不等于高连接数。你优化了一个指标,另一个可能反而变差。
1.1 吞吐量——最容易被误解的指标
吞吐量是大多数人第一个看的指标。但我得说一句:只看吞吐量,你可能会被误导。
举个例子。我在调优一个视频分发平台时,发现 iperf3 测出来的吞吐量能跑到 9.8 Gbps,但实际业务流量一上去,用户还是卡。为什么?因为 iperf3 用的是大包(1460 字节 payload),而业务里有很多小包(64 字节)。大包能跑满带宽,小包就不一定了。
所以,测吞吐量时一定要明确:包大小是多少? 不同包大小下的吞吐量,反映的是不同层面的性能。
1.2 延迟——毫秒级的差距就是生死
延迟这东西,在金融交易系统里就是钱。我记得有一次帮一家券商做性能评估,他们的交易链路要求端到端延迟不超过 100 微秒。我们用 netperf 的 TCP_RR 测试,发现内核协议栈的延迟在 50-80 微秒之间波动。嗯,这个数字看起来还行,但峰值抖动到了 200 微秒——这就不能接受了。
延迟测试要关注两个值:平均值和尾延迟(P99/P999)。平均值好看不代表系统稳定,尾延迟才是真正的杀手。
1.3 PPS——小包场景下的硬指标
PPS 是很多人忽略的指标。你想想看,一个 64 字节的小包,和 1460 字节的大包,在网卡层面处理的开销其实差不多——都要走一遍 DMA、中断、协议栈。但吞吐量上,64 字节包只能跑到大包的 1/20 左右。
我曾经在测试一个 DPDK 改造方案时,发现原生内核协议栈的 PPS 上限大概在 1.5M 左右(单核),再高就开始丢包了。而 DPDK 方案能跑到 10M+。这个差距,就是协议栈处理路径的差异带来的。
我的经验:如果你的业务以小包为主(比如 DNS、HTTP 短连接),PPS 比吞吐量更重要。建议先用 64 字节包做压力测试,看看系统能扛多少 PPS。
1.4 连接数——并发能力的试金石
连接数这个指标,很多人把它和并发数混为一谈。其实不对。连接数指的是系统同时维持的 TCP 连接数量,而并发数是指同时处理的请求数量。
一个典型的场景:Nginx 作为反向代理,可以维持 10 万个长连接,但真正活跃的请求可能只有几百个。这时候瓶颈往往不在 CPU,而在内存——每个 TCP 连接都要占用一个 socket 缓冲区,默认的 tcp_rmem 和 tcp_wmem 加起来可能超过 200KB。10 万个连接,光缓冲区就要 20GB 内存。
2. 基准测试方法论:iperf3 与 netperf
工具选对了,测试就成功了一半。我个人习惯用 iperf3 做吞吐量测试,用 netperf 做延迟和 PPS 测试。为什么?因为各有专长。
2.1 iperf3——吞吐量测试的首选
iperf3 简单、直接、结果清晰。但简单不等于随便跑。我见过有人直接在两个机器上跑 iperf3,中间隔了 10 跳路由器,然后拿着结果说"网络带宽是 100Mbps"——这能信吗?
正确的做法:
- 直连测试:两台机器用网线直连,排除中间设备干扰。
- 多流测试:单流可能跑不满带宽,用
-P 4或-P 8开多个并行流。 - 双向测试:用
-d或--bidir同时测上下行。 - 不同包大小:用
-l参数调整包大小,从 64 到 1460 都测一遍。
# 服务端
iperf3 -s -p 5201
# 客户端:单流 TCP 测试,包大小 1460
iperf3 -c 192.168.1.100 -p 5201 -t 30 -l 1460
# 客户端:多流测试,8 个并行流
iperf3 -c 192.168.1.100 -p 5201 -t 30 -P 8
# 客户端:UDP 测试,指定带宽 1Gbps
iperf3 -c 192.168.1.100 -p 5201 -u -b 1G -l 1400
注意:iperf3 的 UDP 测试默认不限制带宽,如果不加 -b 参数,它会拼命发包,导致测试结果失真。另外,UDP 测试的结果里有个 "Jitter" 字段,那是抖动值,不是延迟,别搞混了。
2.2 netperf——延迟和 PPS 的利器
netperf 比 iperf3 更灵活,尤其适合做延迟和 PPS 测试。它的测试模式很多,我常用的就三个:
| 测试模式 | 命令 | 测什么 |
|---|---|---|
| TCP_STREAM | netperf -H server -l 30 -t TCP_STREAM |
吞吐量 |
| TCP_RR | netperf -H server -l 30 -t TCP_RR |
请求-响应延迟 |
| TCP_CRR | netperf -H server -l 30 -t TCP_CRR |
连接建立+请求-响应延迟 |
TCP_RR 测的是已建立连接上的请求-响应延迟,适合评估长连接场景。TCP_CRR 则包含了三次握手的时间,适合评估短连接场景。这两个值之间的差距,就是连接建立的代价。
我记得有一次,我们在优化一个 HTTP 网关,发现 TCP_CRR 的延迟比 TCP_RR 高了 3 倍。追下去发现是 listen 队列的 backlog 设置太小,导致三次握手阶段有重传。调大 backlog 后,TCP_CRR 的延迟降了 40%。
3. 测试环境搭建与校准
环境搭不好,测试就是白做。我总结了一个"三校准"原则:硬件校准、系统校准、工具校准。
3.1 硬件校准
- 网卡确认:用
ethtool eth0查看网卡速率、双工模式、驱动版本。确保两端协商一致。 - PCIe 带宽:用
lspci -vvv -s 网卡地址查看 PCIe 链路宽度和速率。x8 Gen3 的理论带宽是 8GB/s,如果显示 x1 Gen2,那网卡性能直接砍半。 - 中断绑定:用
cat /proc/interrupts | grep eth0查看中断分布。多队列网卡要把中断分散到不同 CPU 上。
# 查看网卡信息
ethtool eth0
# 查看 PCIe 链路状态
lspci -vvv -s 02:00.0 | grep -i "width\|speed"
# 设置 RPS(Receive Packet Steering)分散中断
echo f > /sys/class/net/eth0/queues/rx-0/rps_cpus
3.2 系统校准
系统参数对测试结果影响巨大。我每次做基准测试前,都会检查这几个关键参数:
| 参数 | 推荐值 | 说明 |
|---|---|---|
| net.core.rmem_max | 134217728 | 接收缓冲区最大值,128MB |
| net.core.wmem_max | 134217728 | 发送缓冲区最大值,128MB |
| net.ipv4.tcp_rmem | 4096 87380 134217728 | TCP 接收缓冲区(min default max) |
| net.ipv4.tcp_wmem | 4096 65536 134217728 | TCP 发送缓冲区(min default max) |
| net.core.netdev_budget | 600 | NAPI 每次轮询处理的包数 |
| net.core.somaxconn | 65535 | listen 队列最大长度 |
一个小技巧:测试前先跑一次 sysctl -w net.ipv4.tcp_timestamps=0 关闭时间戳选项。时间戳会在每个 TCP 头部增加 12 字节,关闭后能减少 CPU 开销,让测试结果更接近硬件极限。
3.3 工具校准
工具本身也会引入误差。我习惯在正式测试前做一次"回环测试"——在同一台机器上跑客户端和服务端,看看工具自身的开销有多大。
# 回环测试:服务端和客户端都在本机
# 终端1
iperf3 -s -p 5201 -B 127.0.0.1
# 终端2
iperf3 -c 127.0.0.1 -p 5201 -t 10
# 结果应该接近 40Gbps+(取决于内存带宽)
# 如果远低于这个值,说明系统或工具有问题
回环测试能帮你排除网卡和线缆的问题。如果回环测试结果正常,但直连测试结果很差,那问题大概率出在网卡、驱动或线缆上。
4. 知识体系总览
下面这张图,把本章的核心逻辑串起来了。你可以把它当作一个检查清单——做性能测试前,对着它过一遍,基本不会漏东西。
5. 避坑指南:我踩过的几个坑
最后,分享几个我实际项目中遇到的坑,希望能帮你少走弯路。
坑一:CPU 亲和性没设置
我曾经在 48 核的机器上跑 netperf,结果发现延迟忽高忽低。排查了半天,发现是客户端和服务端跑在了同一个物理核的兄弟线程上。用 taskset 绑定到不同 NUMA 节点后,延迟稳定了 30%。
坑二:中断合并(coalescing)没关
网卡默认的中断合并策略是为了降低 CPU 使用率,但会引入额外的延迟。用 ethtool -C eth0 rx-usecs 0 tx-usecs 0 关掉合并后,延迟从 200μs 降到了 50μs。当然,CPU 使用率会上升,但基准测试要的是极限性能,不是省电。
坑三:iperf3 的 UDP 测试结果不可重复
iperf3 的 UDP 测试对系统时钟敏感。如果系统时钟有漂移,结果会忽高忽低。我建议用 --omit 5 跳过前 5 秒的数据,等系统稳定后再记录。另外,UDP 测试最好配合 chronyd 或 ptpd 做时间同步。