一、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