必须用--cachegrind-out-file显式指定输出文件,且需配合--tool=cachegrind、-g编译和固定缓存参数(如--I1=32768,8,64),否则生成的cg.out无法被cg_annotate正确解析或用于可靠对比。

使用 --cachegrind-out-file 指定输出路径
默认情况下,cachegrind 会把结果写到标准错误(stderr),混在其他 Valgrind 日志里,根本没法直接解析。必须用 --cachegrind-out-file 显式指定文件名,否则后续所有分析都无从谈起。
常见错误是只写 --log-file ——那只是 Memcheck 的日志,对 cachegrind 完全无效。
-
--cachegrind-out-file必须和--tool=cachegrind同时出现,单独加没用 - 路径支持相对或绝对,比如
--cachegrind-out-file=./report/cg.out或--cachegrind-out-file=/tmp/cg-$(date +%s).out - 文件会被覆盖,不会自动追加;如果并行跑多次,得手动加时间戳或 PID 避免冲突
cachegrind-out-file 文件不能直接 human-readable
生成的 cg.out 是二进制+文本混合格式,头几行是汇总统计,后面是按函数/行号排列的计数块,但字段顺序不固定、有注释行、还带符号地址——人眼几乎无法直接读。
别打开它试图“扫一眼命中率”,这只会浪费时间。正确做法是交给 cg_annotate 或 callgrind_annotate(二者兼容)处理。
- 用
cg_annotate cg.out --auto=yes | head -20看顶层汇总(含 I1/D1/LL 缺失和访问数) - 用
cg_annotate cg.out --show=I1,D1,LL --threshold=0.1筛出贡献超 0.1% 的热点代码 - 若源码路径变了(比如换机器重编译),加
--pid=yes并确保-g编译,否则行号映射错乱
保存前务必确认编译选项和缓存参数
同一份二进制,不同 --I1/--D1 参数跑出来的 cg.out 数值差异极大,甚至不可比。不固定参数就保存,等于存了个废文件。
- 真实 CPU 的 L1d 通常是 32KB/8-way/64B,建议显式写成
--I1=32768,8,64 --D1=32768,8,64 --LL=8388608,16,64 - 必须用
-g编译,否则cg_annotate显示的是汇编地址,不是源码行 - 避免用
-flto:LTO 会丢符号,cachegrind无法关联函数名,cg_annotate只能显示???
不要用 valgrind --log-file 替代 --cachegrind-out-file
有人试过把整个 Valgrind 输出重定向到文件,比如 valgrind --tool=cachegrind ./a.out > log.txt 2>&1,结果发现 log.txt 里只有启动信息和警告,没有缓存数据——因为 cachegrind 的核心计数压根不走 stderr,只写进 --cachegrind-out-file 指向的文件。
更隐蔽的坑是:如果程序本身也写 stderr(比如打印调试日志),和 Valgrind 的启动提示混在一起,会导致 cg_annotate 解析失败,报 invalid file format。
- 唯一安全的保存方式:只依赖
--cachegrind-out-file,其他重定向一律不用 - 验证是否成功:
head -n5 cg.out应该看到类似event: Ir I1mr ILmr Dr D1mr DLmr Dw D1mw DLmw这样的 event 行
-g 和缓存参数固化——没它们,cg.out 文件看着存在,其实等于没存。


















