性能基准测试基础

各位同学好,我是老张。今天咱们聊聊性能基准测试——这个听起来有点学术,但实际上每个嵌入式工程师都绕不开的话题。

我记得刚入行那会儿,带我的师傅扔给我一块板子说:「跑个基准测试看看」。我当时一脸懵,啥是基准测试?为什么要跑?后来踩了不少坑,才慢慢摸清楚这里面的门道。

什么是基准测试

说白了,基准测试就是给系统「称体重」。你想想看,一个人胖不胖,不能光靠眼睛看,得上秤。系统性能好不好,也不能光靠感觉,得有一套标准化的测量方法。

基准测试的定义其实很简单:在可控条件下,用标准化的负载去测量系统的性能指标。这个「可控条件」很关键——你得保证每次测试的环境是一样的,否则结果没法比。

核心要点:基准测试不是功能测试,它不关心系统「能不能做」,而是关心「做得有多快、有多稳、资源消耗有多少」。

我在项目中遇到过最典型的例子:两个团队都说自己的行情解析模块「很快」,结果一测,一个每秒能处理10万笔,另一个只能处理3万笔。没有基准测试,这种争论永远没结果。

为什么需要基准测试

这个问题我问过很多新人,答案五花八门。我总结一下,其实就三个核心原因:

  1. 量化对比——没有数据,你拿什么说服别人你的优化有效?
  2. 发现瓶颈——系统跑得慢,到底慢在哪?基准测试能帮你定位。
  3. 回归验证——改了一行代码,性能是变好了还是变差了?跑一遍基准测试就知道了。

我曾经接手过一个行情系统,客户投诉说「有时候快有时候慢」。我一开始怀疑是网络问题,后来做了基准测试才发现——CPU频率在降频!散热没做好,温度一高就降频,性能自然忽高忽低。你看,没有基准测试,你连问题在哪都找不到。

我的习惯:每次做性能优化之前,先跑一轮基准测试,把数据记录下来。优化完再跑一轮,对比看效果。这叫「用数据说话」。

关键性能指标

基准测试测什么?不是瞎测的。嵌入式行情系统,我重点关注四个指标。下面这张图能帮你快速理解它们之间的关系:

性能基准测试 吞吐量 单位时间处理能力 延迟 单次操作耗时 抖动 延迟的波动程度 CPU/内存占用 资源消耗情况 四个指标相互关联,需要综合评估

1. 吞吐量

吞吐量,就是系统「干活的速度」。对于行情系统来说,通常用「每秒处理的消息数」来衡量。比如你的系统每秒能处理50万笔行情数据,那吞吐量就是500K msg/s。

怎么测?很简单:让系统持续接收行情数据,统计单位时间内成功处理的数量。

// 伪代码示例:测量吞吐量
uint64_t start_time = get_timestamp_ms();
uint64_t count = 0;

while (get_timestamp_ms() - start_time < 1000) {  // 测1秒
    if (process_message()) {
        count++;
    }
}

printf("吞吐量: %lu msg/s\n", count);

注意:吞吐量不是越高越好。我曾经见过一个系统,吞吐量很高,但丢包率也高——因为它把处理不过来的数据直接扔了。这种「虚假繁荣」要不得。

2. 延迟

延迟,就是「从收到数据到处理完成花了多久」。行情系统对延迟极其敏感——你比别人慢1微秒,可能就错过了一笔交易。

延迟通常用百分位来表示:P50(中位数)、P99(99%的请求都在这个延迟以内)、P999(99.9%)。我个人习惯重点看P99和P999,因为最差情况往往才是系统的真实瓶颈。

// 测量单次处理延迟
uint64_t start = get_cycle_count();  // 读CPU周期计数器
process_message();
uint64_t end = get_cycle_count();

uint64_t latency_ns = (end - start) / cpu_freq_mhz;  // 换算为纳秒
printf("延迟: %lu ns\n", latency_ns);

嗯,这里要注意:测量延迟本身也会引入开销。如果你在代码里到处插时间戳,测出来的结果可能比实际偏大。我建议用硬件时间戳或者专用的性能计数器来测,精度更高。

3. 抖动

抖动,说白了就是「延迟的波动程度」。为什么这个指标重要?因为行情系统最怕的就是「忽快忽慢」。你想想看,如果大部分时候延迟是10微秒,但偶尔蹦到100微秒——那这100微秒的尖峰就可能让你丢单。

抖动的衡量方式有很多,最常用的是标准差和最大-最小差值。我习惯看延迟的分布图,能直观看到有没有「长尾」。

我的经验:抖动往往比高延迟更可怕。高延迟你还能预判,抖动完全不可控。我曾经在一个项目里发现,抖动的主要来源是中断处理——一个高优先级的中断打断了行情处理,导致延迟瞬间飙升。后来我们做了中断绑核和优先级调整,抖动降了80%。

4. CPU/内存占用

这个好理解——系统跑了多少资源。嵌入式系统的资源是有限的,你不能为了追求低延迟把CPU吃满,那样其他任务就没法跑了。

CPU占用率用top或perf工具就能看。内存占用要关注两点:一是静态占用(代码段、数据段),二是动态占用(堆、栈)。行情系统里,内存泄漏是常见问题——跑着跑着内存越占越多,最后系统崩了。

指标 测量工具 行情系统典型值 警戒线
CPU占用率 top, perf, htop 30%-60% > 80%
内存占用 free, /proc/meminfo 50-200 MB 持续增长
缓存命中率 perf stat, cachegrind L1 > 90% L1 < 70%

一个小技巧:看CPU占用的时候,别忘了看是用户态还是内核态。如果内核态占用过高,说明系统调用太频繁——这时候就该考虑批处理或者零拷贝了。

四个指标的关系

这四个指标不是孤立的。你想想看:

  • 吞吐量上去了,延迟往往会跟着涨——因为排队时间变长了
  • 延迟降下来了,抖动可能变大——因为你在牺牲稳定性换取速度
  • CPU占用高了,吞吐量不一定线性增长——因为CPU调度开销也在涨

所以做基准测试的时候,不能只看一个指标。我习惯的做法是:先定一个目标场景(比如「每秒处理30万笔行情,P99延迟不超过50微秒」),然后在这个约束下去优化。

好了,这一章的内容就这些。记住一句话:没有基准测试的性能优化,都是耍流氓。下一章咱们会聊怎么搭建测试环境,到时候我会分享一些我踩过的坑——嗯,保证让你少走弯路。


公众号:蓝海资料掘金营,微信deep3321