Ubuntu 下 C++ 性能分析实操指南
一 准备与基线
g++ -std=c++17 -g -O2 -o app app.cpp。taskset -c 0 ./app。sudo apt install linux-tools-common linux-tools-generic g++ build-essential cmake valgrind google-perftools libgoogle-perftools-dev strace。echo 1 | sudo tee /proc/sys/kernel/perf_event_paranoid(临时),以及 echo 0 | sudo tee /proc/sys/kernel/kptr_restrict(临时);生产环境请评估安全影响。二 工具速览与选型
| 工具 | 开销 | 主要用途 | 典型场景 | 关键要点 |
|---|---|---|---|---|
| perf | 低 | CPU 热点、调用栈、硬件事件 | 线上/准线上采样、定位函数级瓶颈 | perf record -g ./app + perf report,支持 perf top、perf stat |
| gperftools CPU Profiler | 低 | 采样 CPU 热点、生成火焰图 | 生产/预发低开销分析 | 代码插桩 ProfilerStart/Stop 或 CPUPROFILE=prof.out;pprof 生成文本/火焰图 |
| Valgrind Callgrind | 高(10–20×) | 指令级热点、调用关系 | 开发阶段精确分析 | callgrind + kcachegrind 可视化 |
| Valgrind Massif | 高 | 堆内存占用与分配栈 | 内存峰值、泄漏定位 | ms_print 查看堆时间线 |
| Valgrind Memcheck | 高 | 内存错误(泄漏、越界、未初始化) | 功能正确性 | --leak-check=full 精确定位 |
| strace | 中 | 系统调用跟踪 | I/O、文件/网络瓶颈 | strace -T -p <PID> 观察耗时 |
| gprof | 中 | 函数级时间占比 | 简单项目、无符号需求 | 编译加 -pg,运行生成 gmon.out 再分析 |
三 快速上手流程
perf record -g ./app(长时间运行可用 -a 全系统或 -p <PID> 指定进程)。perf report 聚焦占比高的函数;需要源码级定位时用 perf annotate。perf top 快速扫热点;统计模式:perf stat ./app。perf_event_paranoid/kptr_restrict。#include <gperftools/profiler.h>,在关键区间 ProfilerStart("prof.out"); ... ProfilerStop();。env CPUPROFILE=prof.out ./app。pprof --text ./app prof.out;生成火焰图:pprof --collapsed ./app prof.out | flamegraph.pl > prof.svg。valgrind --tool=callgrind ./app,用 kcachegrind callgrind.out.* 查看调用图与源码热点。valgrind --tool=massif ./app,用 ms_print massif.out.* 查看堆分配随时间变化。valgrind --tool=memcheck --leak-check=full ./app 定位泄漏与非法访问。strace -T -p <PID> 或 strace -c ./app 汇总系统调用耗时,定位文件/网络瓶颈。四 进阶与系统瓶颈排查
perf annotate 做源码级热点与指令级分析。ulimit -n 调整文件描述符限制、sysctl 调整内核网络/文件系统参数,避免系统配置成为瓶颈。五 常见问题与排错
perf report 看不到内核符号,检查并临时调整 /proc/sys/kernel/kptr_restrict 与 perf_event_paranoid。perf -p <PID> 或绑定 CPU 核心(taskset -c 0-3 ./app)减少调度干扰;对短时程序适当延长采样时间或多次取中位数。pprof 的 --collapsed 输出到 flamegraph.pl。