性能测试分析

测试结果

执行:

1
2
3
4
5
6
sudo ./scripts/benchmark.py \
  --freq 99 \
  --duration 30 \
  --runs 5 \
  --workload "yes > /dev/null" \
  --profiler-symbolize

对 profiler 与 perf 的 benchmark 结果如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
=== 多轮统计汇总-collect-only (20260420_143315, runs=5) ===
tool         cpu_mean(s)  cpu_std(s)   cpu_p95(s)   samples_mean   samples_std    samples_p95   
profiler     0.450000     0.008944     0.460000     2982.800000    3.969887       2987.000000   
perf         0.396000     0.004899     0.400000     2948.400000    3.979950       2954.000000   
cpu_overhead_improvement_vs_perf(%): -13.64

=== 多轮统计汇总-end-to-end (20260420_143315, runs=5) ===
tool         cpu_mean(s)  cpu_std(s)   cpu_p95(s)   samples_mean   samples_std    samples_p95   
profiler     0.450000     0.008944     0.460000     2982.800000    3.969887       2987.000000   
perf         0.880000     0.006325     0.890000     2948.400000    3.979950       2954.000000   
cpu_overhead_improvement_vs_perf(%): 48.86

虽然 e2e 的结果不错,但是 collect only 为什么会差一些呢?

结果分析

这次命令带了:

1
--profiler-symbolize

那 collect-only 对比会明显偏向 perf,因为:

1
2
profiler collect-only = 采集 + 符号化/文本化
perf collect-only     = 只 record 二进制数据

这种情况下,profiler collect-only 差一些完全正常,甚至可以说不是同一口径。

要比较纯采集成本,应该确保 profiler 用默认的 --no-symbolize,也就是不要传 --profiler-symbolize

建议下一步排查

我会优先确认这几件事:

1
2
3
4
5
6
7
# 确认没有开启 profiler 符号化
sudo ./scripts/benchmark.py \
  --freq 99 \
  --duration 30 \
  --runs 10 \
  --workload "yes > /dev/null" \
  --outdir ./report/no_symbolize

然后再单独跑符号化版本:

1
2
3
4
5
6
7
sudo ./scripts/benchmark.py \
  --freq 99 \
  --duration 30 \
  --runs 10 \
  --workload "yes > /dev/null" \
  --outdir ./report/symbolize \
  --profiler-symbolize

如果两者差距很大,说明 collect-only 主要被符号化/输出拖住。

如果默认 --no-symbolize 仍然是 0.466s,那下一步就该看 profiler 采集路径里是否有这些开销点:

  • 每次事件都做了较重的用户态处理
  • 输出文本太频繁
  • BPF map 查询次数太多
  • 栈聚合数据结构有额外成本
  • ring buffer / perf buffer 消费路径不够轻
  • sample 结束后仍有清理或汇总逻辑被算进采集时间
Licensed under CC BY-NC-SA 4.0
使用 Hugo 构建
主题 StackJimmy 设计