2. 性能度量与基准测试

在密码工程中,“快”与“慢”不能凭感觉判断。AES-128 在服务器 CPU 上单核吞吐量可能达到数 GB/s,而同一算法在资源受限的嵌入式 MCU 上可能只有几十 KB/s;RSA-2048 的一次签名延迟可能是毫秒级,而验签延迟往往只有其几分之一。要得到可信、可复现、可比较的结论,必须把“性能”拆解为可测量的指标,并设计受控的基准测试。

一、先明确度量什么:吞吐量、延迟与资源占用

密码算法的性能通常从三个维度刻画。第一是吞吐量(Throughput),表示单位时间内能处理的数据量,常用 MB/s 或 GB/s,适合衡量对称加密、哈希、AEAD 等批量数据场景。第二是延迟(Latency),表示单次操作从输入到输出所需时间,常用微秒(µs)或毫秒(ms),适合衡量密钥交换、签名验签、单次加解密等交互式场景。第三是资源占用,包括 CPU 周期数、指令数、缓存命中率、内存峰值、功耗等,用于评估算法在特定硬件上的实际代价。

三者之间并非线性关系。例如 AES-NI 指令可以极大提升吞吐量,但对单块 16 字节数据的延迟改善有限;而某些抗侧信道实现会牺牲吞吐量换取恒定时间特性。因此基准测试必须明确目标场景,不能只报一个“最快值”。

二、用 openssl speed 建立基线

OpenSSL 自带的 speed 子命令是最常用的对称算法与哈希基线工具。它会对指定算法在多种数据块大小下反复执行,输出每秒处理块数和吞吐量。典型用法如下:

# 测试 AES-128-CBC、AES-256-GCM、SHA-256 的吞吐量
openssl speed -elapsed -evp aes-128-cbc aes-256-gcm sha256

# 指定测试时长(秒)与多线程
openssl speed -seconds 5 -multi 4 -evp aes-128-gcm

# 测试 RSA-2048 签名与验签
openssl speed -seconds 5 rsa2048

输出中 -elapsed 表示使用墙上时钟而非 CPU 时间,-evp 表示使用 EVP 高层接口,-multi N 会启动 N 个进程并行测试。对于 AES-GCM,输出会分别给出 16、64、256、1024、8192、16384 字节块下的吞吐量。观察这些数字时要注意:小数据块下吞吐量通常较低,因为每次调用的固定开销占比高;大数据块下吞吐量趋于稳定,更能反映算法的峰值能力。

openssl speed 的结果受 CPU 频率调节、超线程、NUMA 亲和性影响。建议固定 CPU 频率、关闭节能模式,并用 taskset 绑定核心后再对比。

三、用 perf 观察底层资源占用

openssl speed 给出的是“结果”,perf 则帮助回答“为什么是这个结果”。通过 perf stat 可以统计指令数、周期数、分支预测失败、缓存未命中等硬件事件:

perf stat -e cycles,instructions,cache-misses,branch-misses \
  openssl speed -seconds 3 -evp aes-256-gcm

# 查看热点函数
perf record -g openssl speed -seconds 3 -evp sha256
perf report

如果 instructions per cycle(IPC)很低,说明流水线停顿严重,可能是内存带宽瓶颈或分支预测失败;如果 cache-misses 很高,说明查表型实现(如 T-table AES)受缓存影响大,此时可考虑 AES-NI 或位切片实现。perf 还能配合 perf stat -a 观察整机资源,判断测试是否被其他进程干扰。

四、基准测试设计的关键控制变量

要让结果可比较,必须控制以下变量:

  • 数据规模与块大小:对称算法至少覆盖 16 B、1 KB、64 KB、1 MB 四档,分别代表单块、小包、典型报文和批量流。
  • 密钥与 IV 复用策略:GCM 等模式若重复使用 nonce 会破坏安全性,测试时应每次生成新 IV,或明确说明复用仅用于性能测量。
  • 预热与采样次数:先跑 1~2 秒预热,再取 5 次以上结果的中位数,避免首次运行的冷缓存偏差。
  • 编译与指令集:确认 OpenSSL 是否启用了 AES-NI、AVX2、SHA 扩展,可用 openssl version -a 和 openssl speed -evp 的输出判断。
  • 并发模型:单线程延迟与多线程吞吐量要分开测,避免把线程调度开销算进算法本身。

五、从测量到判断:一个可复现的测试流程

下面给出一个面向 AES-256-GCM 的基准测试流程示例,参数为教学假设值,实际结果需以本机运行为准:

# 1. 固定 CPU 频率并绑定核心
sudo cpupower frequency-set -g performance
taskset -c 2 openssl speed -elapsed -seconds 5 -evp aes-256-gcm

# 2. 记录硬件事件
taskset -c 2 perf stat -e cycles,instructions,cache-misses \
  openssl speed -elapsed -seconds 5 -evp aes-256-gcm

# 3. 对比不同实现
openssl speed -elapsed -seconds 5 -evp aes-256-gcm
OPENSSL_ia32cap="~0x200000200000000" openssl speed -elapsed -seconds 5 -evp aes-256-gcm

第三步通过环境变量屏蔽 AES-NI 与 PCLMULQDQ,可对比“纯软件实现”与“硬件加速实现”的差距。若屏蔽后吞吐量从数 GB/s 降到数百 MB/s,说明硬件加速贡献显著;若延迟指标变化不大,则说明瓶颈在调用开销而非算法本身。

密码算法基准测试:指标—工具—控制变量—判断 吞吐量 MB/s · GB/s 批量数据、流加密 AES-GCM / SHA-256 延迟 µs · ms 单次签名 / 验签 RSA-2048 / ECDSA 资源占用 cycles · IPC cache-misses 内存峰值 / 功耗 openssl speed -evp 高层接口 -elapsed 墙上时钟 -multi N 多进程 -seconds 5 采样时长 输出:块大小 vs 吞吐量 perf stat / record cycles, instructions cache-misses branch-misses perf report 热点函数 判断瓶颈:IPC / 缓存 关键控制变量 • 块大小:16 B / 1 KB / 64 KB / 1 MB • 密钥与 IV:每次新生成,避免复用 • 预热 1–2 s,取 5 次中位数 • 固定 CPU 频率,taskset 绑核 • 确认 AES-NI / AVX2 / SHA 扩展 • 单线程延迟与多线程吞吐分开测 结果判断逻辑 吞吐高、延迟低 → 适合高并发服务 吞吐高、延迟高 → 适合批量离线处理 IPC 低、cache-miss 高 → 查表实现瓶颈 屏蔽 AES-NI 后骤降 → 依赖硬件加速 多线程无提升 → 内存带宽或锁竞争

最后需要强调:基准测试的结论必须附带完整的测试环境说明——CPU 型号、主频、OpenSSL 版本、编译选项、是否启用硬件加速、并发度、数据块大小。缺少这些信息的“性能数字”无法复现,也无法用于工程决策。把 openssl speed 作为基线、perf 作为归因工具、控制变量作为实验纪律,才能让密码算法的性能度量真正服务于系统选型与优化。