0%

Linux基础复学(7)- 性能分析工具perf

前言

perf是Linux内置的性能分析工具,主要是利用了硬件技术单元比如CPU, PMU和软件的计数,软件计数器及跟踪点。
perf的源码在Linux内核源码的tools/perf下。

perf

perf包含许多二级命令,实现不同的功能:

perf

perf list

list显示系统支持的事件类型,主要有hardware, software, tracepoint三类:

  • hardware PMU单元产生的事件
  • software 内核产生的事件,比如进程切换
  • tracepoint 内核静态跟踪点触发的事件

perf record

record用来采集数据并存储到文件中,然后可以使用report命令分析数据。

record有如下几个选项:

  • e 选择一个事件
  • a 全系统范围内采集
  • p 指定一个进程ID
  • o 指定要输出的文件,默认是perf.data
  • g 使能函数调用图功能, 分析时 可以查看调用栈
  • C 只采集某个CPU的数据

report常见的几个选项

  • i 输入待分析的数据文件,默认perf.data
  • g 生产函数调用关系图
  • sort 分类统计信息,比如pid, comm, cpu等

perf stat

stat通过概括,精简的方式对被调试的程序分析展示运行的整体情况,汇总数据,包含如下选项:

  • a 显示所有CPU的统计信息
  • c 显示指定CPU的统计信息
  • e 指定要显示的事件
  • p 指定要显示的进程的ID
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
root@keep-Inspiron-3020-S:/home/keep# perf stat -p 5353

Performance counter stats for process id '5353':

24,937.97 msec task-clock # 0.996 CPUs utilized 真正占用处理器的时间
94 context-switches # 3.769 /sec
1 cpu-migrations # 0.040 /sec 程序运行期间处理器迁移的次数
0 page-faults # 0.000 /sec 发生缺页异常的次数
<not counted> cpu_atom/cycles/ (0.00%)
129,338,465,839 cpu_core/cycles/ # 5.186 GHz
<not counted> cpu_atom/instructions/ (0.00%)
434,900,571,908 cpu_core/instructions/
<not counted> cpu_atom/branches/ (0.00%)
82,583,280,228 cpu_core/branches/ # 3.312 G/sec
<not counted> cpu_atom/branch-misses/ (0.00%)
53,783 cpu_core/branch-misses/
TopdownL1 (cpu_core) # 40.7 % tma_backend_bound
# 0.0 % tma_bad_speculation
# 6.0 % tma_frontend_bound
# 53.3 % tma_retiring

25.025841987 seconds time elapsed

perf top

top命令按占比列出CPU使用比较多的进程,包含以下选项:

  • e 指定要分析的事件
  • p 分析指定进程
  • k 指定内核映像路径
  • K 不显示内核或者内核模块的符号
  • U 不显示用户态程序的符号
  • g 显示函数调用关系

perf

火焰图

下载https://github.com/brendangregg/FlameGraph仓库代码

  1. 首先使用perf record 采集数据生成 perf.data文件
  2. 使用perf script -i perf.data &> perf.unfold 解析
  3. ./stackcollapse-perf.pl perf.unfold &> perf.folded
  4. ./flamegraph.pl perf.folded > perf.svg 生成火焰图

y轴代表调用栈,每一层都是一个函数调用,栈越深则火焰越高,调用关系是从下而上的,即下层函数调用了上层函数。
x轴代表抽样数,一个函数在x轴占据的宽度越宽,则表示它被抽样到的次数也就越多,也就是说它执行的时间越长。

constructor函数编译成静态库后不生效

最近在项目中,为了解耦合代码,使用__attribute__((constructor)) 函数将一些信息在程序运行前自动注入全局变量,当库代码编译成动态库时,的确可以正常工作。但是,编译成静态库的时候,就不生效了。

上网查了一下,大概就是编译成静态库时,链接器会把那些没有被调用到的函数优化掉,因此在最终程序中就没有相关函数了,解决办法就是在链接的时候,在静态库前后添加-Wl,–whole-archive和-Wl,–no-whold-archive,亲测有效!

更多

perf是一个工具,可以帮助我们定位到程序的瓶颈,修改就要看具体的代码了,不断的尝试优化,以达到更优的性能。

今天软考出成绩了,好伤心,没有通过,挂在案例了,最担心的论文反而通过了。案例也的确是练习的不多,下半年再考一次吧,好好学习还是学到了不少东西,结果很重要,但过程也很精彩!

Jsjrk


行动,才不会被动!

欢迎关注个人公众号 微信 -> 搜索 -> fishmwei,沟通交流。

欢迎关注

博客地址: https://fishmwei.github.io

掘金主页: https://juejin.cn/user/2084329776486919