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 算法,在不同的测试环境下跑出来的结果可能差一倍。我习惯把环境影响因素归成三类:

  1. 硬件环境:CPU 型号、主频、缓存大小、内存通道数。比如 Intel Xeon 和 AMD EPYC 的 AES 指令延迟不同,结果就有差异。还有 NUMA 架构,跨 NUMA 节点访问内存会大幅降速。
  2. 软件环境:操作系统版本、内核参数、加密库版本(如 OpenSSL 1.1.1 vs 3.0)、编译器优化级别。我记得 OpenSSL 1.0.2 的 SM4 实现用了查表法,3.0 改成 bitsliced,吞吐量直接提升了 30% 。
  3. 测试工具与配置:压测线程数、数据块大小、运行时长。我曾见过有人用单线程测 SM4,得出 500 MB/s,以为很牛;结果换上 32 线程才发现内存带宽被撑爆,实际只有 1.2 GB/s——线程数不是越多越好。

特别提醒:压测时务必关闭 CPU 节能(如 intel_pstate、acpi_cpufreq 的 ondemand 策略),否则你会发现吞吐量每隔几秒掉一次。我曾经因为忘了关 C-states,排查了三天才找到原因——CPU 降频到 800 MHz,吞吐量对半砍。

下面这张图能帮你快速理清性能测试的基本逻辑:

SM4 吞吐量测试基础框架 SM4 吞吐量测试基础框架 吞吐量性能测试 定义 衡量指标 测试环境 单位时间处理量 区分带宽/延迟 平均/峰值吞吐 P50/P99延迟 CPU/内存利用率 硬件(CPU/内存) 软件(OS/库) 工具配置 关键:三要素互相影响——环境不同,指标结果差异巨大 例:同样的SM4代码,开/关超线程可导致吞吐量波动20%

测试方法:压测与监控,两手都要硬

具体怎么做?我通常分四步:

  • 确定基线:单线程、小数据块(比如 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 值,才有说服力。

吞吐量性能测试,说白了就是“在可控的环境下,用正确的指标,客观地度量系统的能力”。下功夫做好这步,后面的波动排查才能有的放矢。