性能优化是计算机中永恒的话题,它可以让程序尽可能运行得更快。在计算机发展历史中,人们总结了一些性能优化的相关理论,主要的理论如下:
- 二八定律:对于大部分事物,80%的结果是由20%的原因引起的。这是优化可行的理论基础,也启示了程序逻辑优化的侧重点。
- 木桶定律:木桶的容量取决于最短的那块木板。这个原理直接指明了优化的方向,即先找到短板再优化。
- 性能分析:性能优化主要分为 5 个部分,也就是经典的 PAROT 模型。对进行优化的程序进行采样,不同的应用场景下有不同的采样工具,如 Linux分析内核性能的 perf 工具,Intel 公司开发的 VTune 工具。
综上所述,性能优化最重要的两个阶段:分别是性能分析与性能优化。性能分析的目标就是寻找性能瓶颈,查找引发性能问题的根源和瓶颈。在性能分析阶段,需要借助一些性能分析工具。
perf 是一款 Linux 性能分析工具,内置在 Linux 内核的一个 Linux 性能分析框架中,基于内核的 perf_events 子系统,能够对 CPU 性能计数器进行采样,从而帮助开发者分析程序的性能瓶颈、热点函数、缓存命中率等。
核心功能
- 性能监控:实时监控系统或进程的 CPU 使用率、上下文切换、缓存命中率等。
- 性能剖析:通过采样分析程序运行时的函数调用栈,找出最耗时的代码路径。
- 静态/动态追踪:支持跟踪点(tracepoints)、探针(kprobes/uprobes)等,用于分析特定内核事件或用户态函数调用。
关键优势
- 低开销:基于事件采样,对系统性能影响极小。
- 深度集成:直接利用内核硬件计数器,无需修改代码。
- 功能全面:覆盖从硬件事件到软件事件的完整性能分析链路。
典型输出示例
perf report 的输出通常包含:
- Overhead:该函数占用的 CPU 时间百分比。
- Command:进程名。
- Shared Object :所属库(如
[kernel.kallsyms]表示内核函数)。 - Symbol:函数名。
perf 核心命令详解
1. perf list - 列出可用事件
功能:显示所有可监控的性能事件,包括硬件、软件和追踪点事件。
bash
# 列出所有事件(可能几百个)
perf list
# 按类别列出
perf list hardware # 硬件性能计数器事件
perf list software # 软件事件(上下文切换、缺页等)
perf list tracepoint # 内核静态追踪点
perf list pmu # PMU事件
perf list cache # 缓存相关事件
perf list breakpoint # 断点事件
常用事件示例:
bash
# 硬件事件
cpu-cycles OR cycles # CPU周期数
instructions # 指令数
cache-references # 缓存引用
cache-misses # 缓存未命中
branch-instructions OR branches # 分支指令
branch-misses # 分支预测失败
# 软件事件
cpu-clock # CPU时钟
task-clock # 任务时钟
page-faults OR faults # 缺页异常
context-switches OR cs # 上下文切换
cpu-migrations # CPU迁移
# 追踪点事件(具体取决于内核配置)
sched:sched_switch # 进程切换
block:block_rq_issue # 块设备请求发出
syscalls:sys_enter_open # 进入open系统调用
高级用法:
bash
# 查找特定事件
perf list | grep -i cache
perf list | grep -E 'sched:|syscalls:'
# 查看事件详细信息
perf list --details sched:sched_switch
2. perf stat - 统计性能事件
功能:测量程序执行过程中的各种性能计数器。
基本语法:
bash
perf stat [选项] <命令>
常用选项:
-e:指定要监控的事件-p:监控指定PID的进程-C:监控指定CPU核心-r:重复运行并显示统计-a:监控所有CPU(系统级)-d:显示更多细节(L1缓存等)-I:间隔输出
使用示例:
bash
# 1. 基础统计 - 运行命令并显示基本硬件事件
perf stat ls -la
# 2. 指定特定事件
perf stat -e cycles,instructions,cache-references,cache-misses,branches,branch-misses ./myprogram
# 3. 监控运行中的进程
perf stat -p 1234
# 按Ctrl+C停止监控
# 4. 系统级监控
perf stat -a sleep 5
# 5. 多核心监控
perf stat -C 0,1,2,3 ./myprogram
# 6. 间隔输出(每1秒)
perf stat -I 1000 -e cycles,instructions -p 1234
# 7. 重复运行(5次)
perf stat -r 5 ./benchmark
# 8. 详细统计(包含缓存事件)
perf stat -d ./myprogram
输出解析示例:
Performance counter stats for 'ls':
1,234.56 msec task-clock # 0.987 CPUs utilized
123 context-switches # 0.100 K/sec
5 cpu-migrations # 0.004 K/sec
456 page-faults # 0.369 K/sec
2,345,678,901 cycles # 1.900 GHz
1,234,567,890 instructions # 0.53 insn per cycle
123,456,789 branches # 99.987 M/sec
1,234,567 branch-misses # 1.00% of all branches
1.251234567 seconds time elapsed
3. perf top - 实时性能分析
功能 :类似top命令,实时显示系统中CPU开销最高的函数。
基本语法:
bash
perf top [选项]
常用选项:
-e:指定监控事件-p:监控指定PID-C:监控指定CPU-K:隐藏内核符号-U:隐藏用户空间符号-g:显示调用图--sort:排序字段(comm, pid, symbol, dso等)
使用示例:
bash
# 1. 基础用法 - 实时显示系统热点
perf top
# 2. 指定监控事件
perf top -e cache-misses
perf top -e instructions
# 3. 监控特定进程
perf top -p 1234
# 4. 监控特定CPU
perf top -C 0,1
# 5. 显示调用图
perf top -g
# 6. 排序方式
perf top --sort comm,pid,symbol # 按进程名、PID、符号排序
# 7. 过滤显示
perf top -K # 只显示用户空间函数
perf top -U # 只显示内核函数
perf top --no-children # 不显示子函数累计
# 8. 高分辨率采样
perf top -F 1000 # 1KHz采样频率
交互命令(perf top运行中):
h:显示帮助P:按采样数排序E:按事件计数排序s:输入要过滤的符号名z:显示/隐藏零采样函数q:退出
4. perf record/report - 详细性能分析
perf record - 记录性能数据
功能 :收集性能数据并保存到perf.data文件中。
基本语法:
bash
perf record [选项] <命令>
常用选项:
-e:指定事件-p:记录指定PID-g:记录调用栈(重要!)-F:采样频率(Hz)-a:全系统记录-o:指定输出文件--call-graph:调用图记录方式(fp, dwarf, lbr)-C:指定CPU
使用示例:
bash
# 1. 基础记录(默认采样cpu-clock事件)
perf record ./myprogram
# 2. 记录调用栈(关键选项)
perf record -g ./myprogram
# 3. 指定采样频率(1000次/秒)
perf record -F 1000 ./myprogram
# 4. 全系统记录(10秒)
perf record -a sleep 10
# 5. 记录特定事件
perf record -e cycles,cache-misses ./myprogram
# 6. 记录运行中进程
perf record -p 1234
# 7. 指定输出文件
perf record -o mydata.data ./myprogram
# 8. 使用dwarf调试信息记录调用栈(更准确但开销大)
perf record --call-graph dwarf ./myprogram
# 9. 多事件记录
perf record -e cycles -e instructions -e cache-misses ./myprogram
perf report - 分析记录数据
功能 :分析perf record生成的数据文件。
基本语法:
bash
perf report [选项]
常用选项:
-i:指定输入文件--stdio:文本模式输出-g graph:显示调用图-n:显示采样数--sort:排序字段-s:指定聚合字段-C:过滤CPU
使用示例:
bash
# 1. 交互式分析(默认)
perf report
# 2. 文本模式输出
perf report --stdio
# 3. 指定数据文件
perf report -i perf.data.old
# 4. 显示调用图
perf report -g graph,callee
# 5. 按进程过滤
perf report --pid 1234
# 6. 按函数过滤
perf report --symbol-filter myfunction
# 7. 统计信息
perf report --header-only # 只显示头部信息
perf report --stats # 显示统计信息
# 8. 高级分析
perf report --sort comm,dso,symbol # 自定义排序
perf report -s symbol,pid # 按符号和PID聚合
interactive模式快捷键:
h:帮助UP/DOWN:导航ENTER:展开/折叠a:标注当前函数P:按百分比排序t:按总时间排序s:搜索符号q:退出
实战工作流程示例
bash
# 1. 快速定位热点程序
perf top
# 2. 发现热点程序PID为5678,进一步分析
perf stat -p 5678
# 3. 详细记录该进程性能数据(30秒)
perf record -g -p 5678 sleep 30
# 4. 分析记录结果
perf report -g graph
# 5. 发现热点函数后,针对性优化并验证
perf stat -e cycles,instructions,cache-misses ./optimized_program
常用组合命令
bash
# 完整性能分析流程
perf record -g -F 999 ./myprogram
perf report --stdio | head -50
# 比较优化前后性能
perf stat -r 10 ./original_program
perf stat -r 10 ./optimized_program
# 实时监控关键指标
watch -n 1 "perf stat -p 1234 2>&1 | tail -8"
# 批量分析多个程序
for prog in test_*; do
echo "=== Testing $prog ==="
perf stat ./$prog 2>&1 | grep -E 'seconds|instructions|cycles'
done
这些命令组合使用,可以覆盖从快速定位问题到深度分析优化的完整性能调优流程。