Ubuntu 系统下性能剖析工具: perf

perf 是内置于 Linux 内核源码树中的性能剖析(profiling)工具。

它基于事件采样原理,以性能事件为基础,支持针对处理器相关性能指标与操作系统相关性能指标的性能剖析。常用于性能瓶颈的查找与热点代码的定位。


1. 安装 perf

在大多数 Linux 发行版中,perf 工具包含在 linux-tools 包中。可以通过包管理器安装:

  • Debian/Ubuntu:
bash 复制代码
sudo apt-get install linux-tools-common linux-tools-generic
  • Red Hat/CentOS:
bash 复制代码
sudo yum install perf
2. 基本使用
列出可用事件

列出所有可用的性能事件(包括硬件和软件事件):

bash 复制代码
perf list
记录性能数据

记录目标程序的性能数据。例如,以99Hz频率对所有CPU采样并记录调用栈信息6秒:

bash 复制代码
perf record -g -a -F 99 sleep 6

可以指定特定事件类型来分析,如CPU时钟周期、缓存命中等:

bash 复制代码
perf record -e cpu-clock -a sleep 6

跟踪点用于跟踪系统调用等预定义事件:

bash 复制代码
perf record -e 'syscalls:sys_enter_*' -a sleep 6

perf record 的可选参数

参数 描述 示例 备注
-e 选择性能事件。可以是 CPU 周期、缓存未命中等。使用 perf list 命令来查看所有可用的事件。 perf record -e cpu-clock ./your_program 适用于指定要监控的性能事件类型
-a 记录整个系统的性能数据,而不仅仅是一个进程。这对于分析系统级的性能问题非常有用。 perf record -a sleep 6 允许对整个系统的性能进行剖析
-p <pid> 记录指定进程的性能数据。只关注某一个特定进程。 perf record -p 12345 sleep 6 <pid> 是目标进程的进程ID
-t <tid> 记录指定线程的性能数据。用于分析多线程程序中某个特定线程的性能。 perf record -t 12345 sleep 6 <tid> 是目标线程的线程ID
-o <file> 指定输出文件名。默认情况下,perf 会将数据保存在当前目录下的 perf.data 文件中。 perf record -o my_output.data ./your_program 自定义性能数据的存储位置
-g 记录函数调用关系(调用栈)。这对于分析程序中函数调用和热点非常有帮助。 perf record -g ./your_program 提供了函数调用链的信息,有助于理解代码执行路径
-c <count> 设置事件的采样周期。例如,每发生1000次事件采样一次。 perf record -c 1000 ./your_program 控制基于计数器的采样频率
-F <frequency> 设置事件的采样频率。例如,每秒采样1000次。 perf record -F 1000 ./your_program 控制基于时间的采样频率

使用建议

  • 系统级分析 :如果你希望对整个系统进行性能分析,可以使用 -a 参数。
  • 特定进程/线程分析 :对于专注于分析特定的进程或线程的情况,分别使用 -p-t 参数。
  • 函数调用关系 :当需要理解程序的函数调用关系,尤其是在定位性能热点时,-g 参数非常重要。
  • 简单开始 :在实际使用中,一开始可以只用 perf record ./your_program 来进行简单的性能记录,然后根据具体需求添加不同的参数。
分析性能数据

使用 perf report 分析记录的数据,默认读取当前目录下的 perf.data 文件。可使用 -i 指定其他文件。


3. 使用示例

一个简单的 C++ 程序比较 push_backemplace_back 的性能差异。编译和运行后,使用 perf 工具进行性能分析。

由于 emplace_back 避免了对象的复制,所以在这种情况下,它会显示出更好的性能。

  • push_back 的性能热点

  • ComplexObject::ComplexObject(int) 被频繁调用,且每次调用都伴随着内存分配和初始化。

  • 构造函数和析构函数的调用占用了大量 CPU 时间(例如,ComplexObject::ComplexObject(int) 占比 4.12%,ComplexObject::~ComplexObject() 占比 2.94%)。

  • std::vector::push_back 涉及到更多的复制或移动操作,这可能导致更高的开销。

  • ComplexObject::ComplexObject(int) 占比 4.71%,表示构造函数被频繁调用。
  • std::vector<ComplexObject, std::allocator<ComplexObject> >::~vector() 占比 3.53%,表示析构函数也被频繁调用。
  • void std::vector<ComplexObject, std::allocator<ComplexObject>>::push_back(ComplexObject const&) 占比 2.94%,这可能涉及到对象的复制或移动操作。

emplace_back 的性能优势

  • emplace_back 直接在向量中构造对象,减少了临时对象的创建和销毁,从而降低了构造函数和析构函数的调用次数。
  • 这种方式避免了不必要的复制或移动操作,因此通常会更快。
4. 其他功能
  • 实时性能监控 : 使用 perf top 查看实时性能热点。
  • 注解(Annotate): 对特定函数或代码行进行源代码级别的性能分析。
  • 事件计数 : 使用 perf stat 统计特定事件的发生次数。
5. 高级用法
  • 调试符号: 确保程序带有调试符号以获得更详细的信息。
  • CPU Cache 分析: 分析缓存使用情况。
  • 硬件计数器: 分析底层事件如分支预测错误。
  • 系统调用跟踪 : 使用 perf trace 跟踪系统调用。
  • 脚本接口: 生成自定义报告。
6. 注意事项

调整 /proc/sys/kernel/perf_event_paranoid/proc/sys/kernel/kptr_restrict 设置,允许非特权用户使用性能分析功能。

7. 可能遇到的问题
问题1: perf_event_paranoid 设置限制

根据错误信息,可能需要降低 perf_event_paranoid 设置值,以允许当前用户使用 perf 工具。可以临时或永久调整此设置。

问题2: kptr_restrict 设置导致内核样本无法解析

由于 kptr_restrict 设置,内核符号被限制访问。可以临时或永久调整此设置,或者确保有匹配的 vmlinux 文件用于解析内核样本。

注意:调整这些设置可能会带来安全风险,应谨慎操作,并考虑生产环境中的安全性需求。

相关推荐
好像是个likun6 分钟前
使用docker拉取镜像很慢或者总是超时的问题
运维·docker·容器
White_Mountain1 小时前
在Ubuntu中配置mysql,并允许外部访问数据库
数据库·mysql·ubuntu
cominglately3 小时前
centos单机部署seata
linux·运维·centos
魏 无羡3 小时前
linux CentOS系统上卸载docker
linux·kubernetes·centos
coder_pig3 小时前
📝小记:Ubuntu 部署 Jenkins 打包 Flutter APK
flutter·ubuntu·jenkins
CircleMouse3 小时前
Centos7, 使用yum工具,出现 Could not resolve host: mirrorlist.centos.org
linux·运维·服务器·centos
Karoku0663 小时前
【k8s集群应用】kubeadm1.20高可用部署(3master)
运维·docker·云原生·容器·kubernetes
木子Linux4 小时前
【Linux打怪升级记 | 问题01】安装Linux系统忘记设置时区怎么办?3个方法教你回到东八区
linux·运维·服务器·centos·云计算
鹏大师运维4 小时前
聊聊开源的虚拟化平台--PVE
linux·开源·虚拟化·虚拟机·pve·存储·nfs