3. 性能测试基础:吞吐量定义、衡量指标、测试环境
提到性能测试,很多人第一反应就是“跑个压测,看每秒能处理多少请求”。但做 SM4 这类对称加密性能测试,光看一个数远远不够。我今天把这章的基础概念拆开来聊,希望能帮你少走弯路。
吞吐量到底是个啥?
我个人的理解是:吞吐量是系统在单位时间内实际完成的工作量。对 SM4 来说,就是每秒加密(或解密)了多少字节。注意,这里说的是“实际完成”,不是理论峰值。
举个例子:一个 SM4 实现标称能跑 1 GB/s,但加了上下文切换、内存拷贝、硬件中断之后,实际测出来可能只有 600 MB/s。这中间的差值,就是落地的代价。说白了,吞吐量是结果,不是口号。
| 概念 | 说明 | SM4 场景举例 |
|---|---|---|
| 吞吐量(Throughput) | 单位时间内完成的数据处理量 | 2.3 GB/s(加密 1 MB 块) |
| 带宽(Bandwidth) | 链路或总线能承载的最大传输能力 | PCIe Gen3 x16 ~16 GB/s,但实际用不满 |
| 延迟(Latency) | 单个操作从发起到完成的时间 | 单次 SM4 加密 ~200 ns |
| 并发数(Concurrency) | 同时进行的请求/任务数量 | 32 线程同时加密 |
你看,吞吐量不等于带宽。我在项目中遇到过有人拿万兆网卡的带宽去评估加密性能,结果差了十几倍。一定要区分系统出口的“能跑多快”和“真正跑了多少”。
衡量指标:别只盯一个数
衡量 SM4 吞吐量,常见指标分成两类:
- 吞吐量:MB/s 或 GB/s,最直观。但要注意数据块大小——加密 64 字节和加密 1 MB 的吞吐量可能差 5 倍。
- 相对吞吐量:比如每秒操作数(Ops/s),适用于固定包长场景。
更细一点,我建议看下面几个维度的组合:
| 指标 | 定义 | 为什么重要 |
|---|---|---|
| 平均吞吐量 | 整个测试周期的均值 | 反映稳态能力 |
| 峰值吞吐量 | 短时间内的最高值 | 可能受缓存预热影响 |
| P50 / P99 延迟 | 请求响应时间的百分位 | 延迟抖动会拉低实际吞吐量 |
| CPU 使用率 | 加密线程占用的核心比例 | 判断瓶颈在计算还是 I/O |
| 内存带宽利用率 | 实际内存读写带宽 vs 理论峰值 | SM4 常受内存带宽制约 |
我曾经踩过一个坑:只报平均吞吐量,结果线上晚高峰时 P99 延迟从 2 ms 跳到 50 ms,系统直接雪崩。后来我把“吞吐量 + 延迟分布”作为硬指标,才真正能反映用户体验。
测试环境:坑比想象的深
同一个 SM4 算法,在不同的测试环境下跑出来的结果可能差一倍。我习惯把环境影响因素归成三类:
- 硬件环境:CPU 型号、主频、缓存大小、内存通道数。比如 Intel Xeon 和 AMD EPYC 的 AES 指令延迟不同,结果就有差异。还有 NUMA 架构,跨 NUMA 节点访问内存会大幅降速。
- 软件环境:操作系统版本、内核参数、加密库版本(如 OpenSSL 1.1.1 vs 3.0)、编译器优化级别。我记得 OpenSSL 1.0.2 的 SM4 实现用了查表法,3.0 改成 bitsliced,吞吐量直接提升了 30% 。
- 测试工具与配置:压测线程数、数据块大小、运行时长。我曾见过有人用单线程测 SM4,得出 500 MB/s,以为很牛;结果换上 32 线程才发现内存带宽被撑爆,实际只有 1.2 GB/s——线程数不是越多越好。
特别提醒:压测时务必关闭 CPU 节能(如 intel_pstate、acpi_cpufreq 的 ondemand 策略),否则你会发现吞吐量每隔几秒掉一次。我曾经因为忘了关 C-states,排查了三天才找到原因——CPU 降频到 800 MHz,吞吐量对半砍。
下面这张图能帮你快速理清性能测试的基本逻辑:
测试方法:压测与监控,两手都要硬
具体怎么做?我通常分四步:
- 确定基线:单线程、小数据块(比如 256 字节),测出算法本身的硬件极限。
- 线性扩展测试:逐步增加线程数,观察吞吐量是否线性增长。一旦出现拐点,就是瓶颈出现了。
- 混合负载测试:模拟真实应用场景,比如加密、解密、签名交替执行。这里要特别注意上下文切换带来的开销。
- 监控关键资源:用 perf、top、sar 等工具实时抓取 CPU 利用率、缓存命中率、内存带宽。我在排查 SM4 吞吐量波动时,曾用
perf stat -e cycles,instructions,cache-misses定位到了 cache 颠簸问题。
小技巧:压测前一定要做“预热”。我习惯让 SM4 循环加密 10 秒钟,等 CPU 频率稳定下来再开始采集数据。否则前几秒的峰值数据会污染整体结果。
避坑指南
最后,给你三个我实战中摔过的坑:
- 坑一:忽视 NUMA 影响。 曾经一台双路服务器,进程绑定到 Node 0,但内存分配在 Node 1,结果吞吐量掉了 40%。后来加了
numactl --membind=0才正常。 - 坑二:压测参数不合理。 数据块太小(<64 字节)会导致大部分时间花在函数调用上,测不出真实加解密速度;块太大(>2 MB)又会被内存拷贝淹没。一般选 1~64 KB 比较合适。
- 坑三:只测一次。 我见过一个测试报告只有一组数据,声称 SM4 能达到 5 GB/s。但换个操作系统版本,换几个核心温度条件,结果可能就变成了 3 GB/s。至少跑 5 轮,取中位数或 P90 值,才有说服力。
吞吐量性能测试,说白了就是“在可控的环境下,用正确的指标,客观地度量系统的能力”。下功夫做好这步,后面的波动排查才能有的放矢。