文档目录

一、和 perf 的区别

perf(采样):
    每隔 N 微秒采样一次 CPU 的 PC 寄存器
    快(几乎不影响程序运行速度)
    统计结果有误差(采样丢失)

Callgrind(模拟):
    用 Valgrind 的虚拟 CPU 模拟执行每条指令
    慢(慢 20-30 倍)
    结果精确(统计了每一条指令、每次缓存访问)

二、基本用法

# 运行 Callgrind
valgrind --tool=callgrind ./my_program

# 输出文件:callgrind.out.12345 (pid=12345)

# 查看函数排行
callgrind_annotate callgrind.out.12345

# 输出示例:
# --------------------------------------------------------------------------
# Ir (指令数)   Dr (读)    Dw (写)    L1m (L1 Miss)  L2m (L2 Miss)  function
# --------------------------------------------------------------------------
# 12,345,678    4,321,000  2,100,000  123,456        12,345         motion_search
#  8,234,567    3,100,000  1,500,000   89,012         8,901         dct_transform
#  2,345,678      900,000    400,000  234,567        23,456         memcpy
#    567,890      200,000    100,000    1,234           123         frame_copy

# 重要指标:
# Ir(Instructions)—— 总指令数,越多的函数越值得优化
# L1m / L2m —— 缓存不命中率,越高说明内存访问模式越差

# 可以清晰看到:
# motion_search 指令数最多(12M),且 L1 Miss 也高(123K)
# → 优先优化这个函数,且优化方向是改善内存访问模式

三、可视化分析

# 用 KCachegrind(GUI 工具)打开
kcachegrind callgrind.out.12345

# 可以在图形界面中看到:
# - 函数调用关系的图(谁调了谁,花费了多少指令)
# - 每个函数的指令数/缓存 Miss 数/分支预测失败数
# - 源码级别的指令开销
# - 热路径(哪个调用链最耗时)