一、perf性能分析
perf是Linux内置的性能分析工具,可采样CPU周期、缓存命中率、分支预测失败等硬件事件,是定位C++性能瓶颈的利器。
1.1 基本使用
# perf stat:统计概要
perf stat -e cycles,instructions,cache-misses ./my_program
# 输出:
# 12,345,678 cycles # CPU总周期
# 8,234,567 instructions # 总指令数
# 123,456 cache-misses # L1缓存未命中
# 1.50 cycles per instruction # IPC,>1说明ILP好
# perf record:采样记录
perf record -g -e cpu-clock --call-graph dwarf ./my_program
# -g: 记录调用栈
# -e cpu-clock: CPU时间采样
# --call-graph dwarf: 用DWARF调试信息重建栈帧
# perf report:查看结果
perf report
# 进入交互界面,按 hottest 排序查看热点函数
二、火焰图(Flame Graph)
2.1 生成与解读
# perf + FlameGraph 生成火焰图
perf record -F 99 -g -- ./my_program --input data.txt
# 生成折叠栈
perf script | stackcollapse-perf.pl > out.folded
# 生成火焰图
./flamegraph.pl out.folded > profile.svg
# 火焰图解读:
# 横轴:样本数(越长越热)
# 纵轴:调用栈深度
# 每个方块:从上到下的调用链
#
# main()
# process() ← 宽=热门函数
# compute() ← 尖峰=叶子函数(不做调用,开销在此)
# math()
# 颜色含义(一般可忽略):
# 暖色(红/橙):热路径
# 冷色(蓝):低频路径
2.2 热点定位实战
# 找出LLC(最后一级缓存)miss热点
perf record -e LLC-load-misses,LLC-store-misses -g ./program
perf report --symbol-filter='*compute*'
# 找出分支预测失败
perf record -e branch-misses -g ./program
perf report
# 找出CPU停滞周期
perf record -e cpu-clock -g ./program
perf report --stdio | head -50
三、AddressSanitizer(ASAN)
# 编译时加ASAN(内存错误检测)
g++ -fsanitize=address -g program.cpp -o program
# 检测类型:
# ① use-after-free(释放后使用)
# ② heap-buffer-overflow(堆越界读写)
# ③ stack-buffer-overflow(栈越界)
# ④ global-buffer-overflow(全局区越界)
# ⑤ memory leaks(内存泄漏)
# ⚠️ 性能开销:约2倍内存 + 2倍CPU
# 只用于测试/调试,不要用于生产
# 配合GDB:
gdb ./program
(gdb) run
# ASAN报告示例:
# ERROR: AddressSanitizer: heap-buffer-overflow on address 0x...
# READ of size 4 at 0x7fff1234 by thread T0:
# #0 0x401234 in process_data src.cpp:45
# #1 0x402345 in main src.cpp:67
四、CMake + Sanitizers配置
# CMakeLists.txt配置多套 sanitizer
option(ENABLE_SANITIZERS "Enable sanitizers for debugging" OFF)
if(ENABLE_SANITIZERS)
set(SANITIZER_FLAGS
-fsanitize=address
-fsanitize=undefined
-fno-omit-frame-pointer
)
add_compile_options(${SANITIZER_FLAGS})
add_link_options(${SANITIZER_FLAGS})
endif()
# 构建:
# debug构建启用:
# $ cmake -B build -DENABLE_SANITIZERS=ON
# $ cmake --build build
# $ ./build/program
# 生产构建(无sanitizer):
# $ cmake -B build -DCMAKE_BUILD_TYPE=Release
# $ cmake --build build -C Release