Linux 性能分析工具perf使用

Perf介绍

系统级性能优化通常包括两个阶段:性能剖析(performance profiling)和代码优化。性能剖析的目标是寻找性能瓶颈,查找引发性能问题的原因及热点代码。代码优化的目标是针对具体性能问题而优化代码或编译选项,以改善软件性能。本篇主要讲性能分析中常用的工具——perf。

perf是一款Linux性能分析工具。

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

Linux性能计数器是一个新的基于内核的子系统,它提供一个性能分析框架,比如硬件(CPU、PMU(Performance Monitoring Unit))功能和软件(软件计数器、tracepoint)功能。通过perf,应用程序可以利用PMU、tracepoint和内核中的计数器来进行性能统计。它不但可以分析制定应用程序的性能问题(per thread),也可以用来分析内核的性能问题。

总之perf是一款很牛逼的综合性分析工具,大到系统全局性性能,再小到进程线程级别,甚至到函数及汇编级别。

Perf基本原理

 perf的基本原理都是对被监测对象进行采样,最简单的情形是根据 tick 中断进行采样,即在 tick 中断内触发采样点,在采样点里判断程序当时的上下文。

事件分为以下三种:

1)Hardware Event 是由 PMU 硬件产生的事件,比如 cache 命中,当您需要了解程序对硬件特性的使用情况时,便需要对这些事件进行采样;

2)Software Event 是内核软件产生的事件,比如进程切换,tick 数等 ;

3)Tracepoint event 是内核中的静态 tracepoint 所触发的事件,这些 tracepoint 用来判断程序运行期间内核的行为细节,比如 slab 分配器的分配次数等。

CPU周期(cpu-cycles)是默认的性能事件,所谓的CPU周期是指CPU所能识别的最小时间单元,通常为亿分之几秒,是CPU执行最简单的指令时所需要的时间,例如读取寄存器中的内容,也叫做clock tick。

 

Perf使用

Perf是一个包含23种子工具的工具集
序号 命令 作用
1 annotate 解析perf record生成的perf.data文件,显示被注释的代码。
2 archive 根据数据文件记录的build-id,将所有被采样到的elf文件打包。利用此压缩包,可以再任何机器上分析数据文件中记录的采样数据。
3 bench perf中内置的benchmark,目前包括两套针对调度器和内存管理子系统的benchmark。
4 buildid-cache 管理perf的buildid缓存,每个elf文件都有一个独一无二的buildid。buildid被perf用来关联性能数据与elf文件。
5 buildid-list 列出数据文件中记录的所有buildid。
6 diff 对比两个数据文件的差异。能够给出每个符号(函数)在热点分析上的具体差异。
7 evlist 列出数据文件perf.data中所有性能事件。
8 inject 该工具读取perf record工具记录的事件流,并将其定向到标准输出。在被分析代码中的任何一点,都可以向事件流中注入其它事件。
9 kmem 针对内核内存(slab)子系统进行追踪测量的工具
10 kvm 用来追踪测试运行在KVM虚拟机上的Guest OS。
11 list 列出当前系统支持的所有性能事件。包括硬件性能事件、软件性能事件以及检查点。
12 lock 分析内核中的锁信息,包括锁的争用情况,等待延迟等。
13 mem 内存存取情况
14 record 收集采样信息,并将其记录在数据文件中。随后可通过其它工具对数据文件进行分析。
15 report 读取perf record创建的数据文件,并给出热点分析结果。
16 sched 针对调度器子系统的分析工具。
17   执行perl或python写的功能扩展脚本、生成脚本框架、读取数据文件中的数据信息等。
18 stat 执行某个命令,收集特定进程的性能概况,包括CPI、Cache丢失率等。
19 test perf对当前软硬件平台进行健全性测试,可用此工具测试当前的软硬件平台是否能支持perf的所有功能。
20 timechart 针对测试期间系统行为进行可视化的工具
21 top 类似于linux的top命令,对系统性能进行实时分析。
22 trace 关于syscall的工具。
23 probe 用于定义动态检查点。

全局性概况:

perf list查看当前系统支持的性能事件;

perf bench对系统性能进行摸底;

perf test对系统进行健全性测试;

perf stat对全局性能进行统计;

全局细节:

perf top可以实时查看当前系统进程函数占用率情况;

perf probe可以自定义动态事件;

特定功能分析:

perf kmem针对slab子系统性能分析;

perf kvm针对kvm虚拟化分析;

perf lock分析锁性能;

perf mem分析内存slab性能;

perf sched分析内核调度器性能;

perf trace记录系统调用轨迹;

最常用功能perf record,可以系统全局,也可以具体到某个进程,更甚具体到某一进程某一事件;可宏观,也可以很微观。

pref record记录信息到perf.data;

perf report生成报告;

perf diff对两个记录进行diff;

perf evlist列出记录的性能事件;

perf annotate显示perf.data函数代码;

perf archive将相关符号打包,方便在其它机器进行分析;

perf 将perf.data输出可读性文本;

可视化工具perf timechart

perf timechart record记录事件;

perf timechart生成output.svg文档;

以下是最常用的5种

perf top 类似系统命令 查看消耗cpu比较高的内核函数或者进程

对于一个指定的性能事件(默认是CPU周期),显示消耗最多的函数或指令。

System profiling tool.

Generates and displays a performance counter profile in real time.

perf top [-e | --event=EVENT] []

perf top主要用于实时分析各个函数在某个性能事件上的热度,能够快速的定位热点函数,包括应用程序函数、

模块函数与内核函数,甚至能够定位到热点指令。默认的性能事件为cpu cycles。

使用例子

1、实时显示占用 CPU 时钟最多的函数或者指令(可以用来查找热点函数)

# perf top
$ perf top
Samples: 833  of event 'cpu-clock', Event count (approx.): 97742399
Overhead  Shared Object       Symbol
   7.28%  perf                [.] 0x00000000001f78a4
   4.72%  [kernel]            [k] vsnprintf
   4.32%  [kernel]            [k] module_get_kallsym
   3.65%  [kernel]            [k] _raw_spin_unlock_irqrestore
...

输出结果中,第一行包含三个数据,

  • 分别是采样数(Samples)
  • 事件类型(event)
  • 事件总数量(Event count)。

比如这个例子中,perf 总共采集了 833 个 CPU 时钟事件,而总事件数则为 97742399。

再往下看是一个表格式样的数据,每一行包含四列,分别是:
  • 第一列 Overhead ,是该符号的性能事件在所有采样中的比例,用百分比来表示。
  • 第二列 Shared ,是该函数或指令所在的动态共享对象(Dynamic Shared Object),如内核、进程名、动态链接库名、内核模块名等。
  • 第三列 Object ,是动态共享对象的类型。比如 [.] 表示用户空间的可执行程序、或者动态链接库,而 [k] 则表示内核空间。
  • 最后一列 Symbol 是符号名,也就是函数名。当函数名未知时,用十六进制的地址来表示。

2、-g开启调用关系分析,-p指定的进程号21515

# perf top -g -p 21515

注意:使用方向键切换进程,再按下回车键展开某个进程的调用关系。

perf list 列出perf支持的事件

Perf ist用来查看perf所支持的性能事件,有软件的也有硬件的。

List all symbolic event types.

perf list [hw | sw | cache | tracepoint | event_glob]

性能事件的分布

hw:Hardware event,9个

sw:Software event,9个

cache:Hardware cache event,26个

tracepoint:Tracepoint event,775个

sw实际上是内核的计数器,与硬件无关。

hw和cache是CPU架构相关的,依赖于具体硬件。

tracepoint是基于内核的ftrace,主线2.6.3x以上的内核版本才支持。

指定性能事件(以它的属性)

-e : u // userspace

-e : k // kernel

-e : h // hypervisor

-e : G // guest counting (in KVM guests)

-e : H // host counting (not in KVM guests)

使用例子

1、显示内核和模块中,消耗最多CPU周期的函数:

# perf top -e cycles:k

2、显示分配高速缓存最多的函数:

# perf top -e kmem:kmem_cache_alloc


perf stat 统计profiling进程的各种信息

用于分析指定程序的性能概况。

Run a command and gather performance counter statistics.

perf stat [-e | --event=EVENT] [-a]

perf stat [-e | --event=EVENT] [-a] - []

输出格式

# perf stat ls

输出包括ls的执行时间,以及10个性能事件的统计。

task-clock:任务真正占用的处理器时间,单位为ms。CPUs utilized = task-clock / time elapsed,CPU的占用率。

context-switches:上下文的切换次数。

CPU-migrations:处理器迁移次数。Linux为了维持多个处理器的负载均衡,在特定条件下会将某个任务从一个CPU

迁移到另一个CPU。

page-faults:缺页异常的次数。当应用程序请求的页面尚未建立、请求的页面不在内存中,或者请求的页面虽然在内

存中,但物理地址和虚拟地址的映射关系尚未建立时,都会触发一次缺页异常。另外TLB不命中,页面访问权限不匹配

等情况也会触发缺页异常。

cycles:消耗的处理器周期数。如果把被ls使用的cpu cycles看成是一个处理器的

可以用cycles / task-clock算出。

stalled-cycles-frontend:略过。

stalled-cycles-backend:略过。

instructions:执行了多少条指令。IPC为平均每个cpu cycle执行了多少条指令。

branches:遇到的分支指令数。branch-misses是预测错误的分支指令数。

常用参数

-p:stat events on existing process id (comma separated list). 仅分析目标进程及其创建的线程。

-a:system-wide collection from all CPUs. 从所有CPU上收集性能数据。

-r:repeat command and print average + stddev (max: 100). 重复执行命令求平均。

-C:Count only on the list of CPUs provided (comma separated list), 从指定CPU上收集性能数据。

-v:be more verbose (show counter open errors, etc), 显示更多性能数据。

-n:null run - don't start any counters,只显示任务的执行时间 。

-x SEP:指定输出列的分隔符。

-o file:指定输出文件,--append指定追加模式。

--pre :执行目标程序前先执行的程序。

--post :执行目标程序后再执行的程序。

使用例子

1、执行10次程序,给出标准偏差与期望的比值:

# perf stat -r 10 ls > /dev/null

2、显示更详细的信息:

# perf stat -v ls > /dev/null

3、只显示任务执行时间,不显示性能计数器:

# perf stat -n ls > /dev/null

4、单独给出每个CPU上的信息:

# perf stat -a -A ls > /dev/null

5、ls命令执行了多少次系统调用:

# perf stat -e syscalls:sys_enter ls

perf record profiling进程的数据,并生成 xx.data文件(默认在执行命令的路径下)

收集采样信息,并将其记录在数据文件中。

随后可以通过其它工具(perf-report)对数据文件进行分析,结果类似于perf-top的。

常用参数

-e:Select the PMU event.

-a:System-wide collection from all CPUs.

-p:Record events on existing process ID (comma separated list).

-A:Append to the output file to do incremental profiling.

-f:Overwrite existing data file.

-o:Output file name.

-g:Do call-graph (stack chain/backtrace) recording.

-C:Collect samples only on the list of CPUs provided.

使用例子

1、记录性能事件,等待大约15秒后按 Ctrl+C 退出

# perf record -g

2、记录nginx进程的性能数据:

# perf record -p `pgrep -d ',' nginx`

3、记录执行ls时的性能数据:

# perf record ls -g

4、记录执行ls时的系统调用,可以知道哪些系统调用最频繁:

# perf record -e syscalls:sys_enter ls

perf report 读取xx.data文件

读取perf record创建的数据文件,并给出热点分析结果。
使用例子
1、查看报告
# perf report
 
 
火焰图
 
使用perf record记录采样数据

perf record -e cpu-clock -g -p 4522

使用ctrl+c中断perf进程,或者在程序执行结束后,会产生perf.data的文件,使用report会产生结果分析,如图
perf report
在这里插入图片描述

上面通过文件查看不够直观,还有一种火焰图分析的方式:
工具下载:
git clone https://github.com/brendangregg/FlameGraph.git
使用命令:

使用perf script工具对perf.data进行解析perf script -i perf.data &> perf.unfold
将perf.unfold中的符号进行折叠:/data/stackcollapse-perf.pl perf.unfold &> perf.folded
最后生成svg图:/data/flamegraph.pl perf.folded > perf.svg

然后可以通过chrome或者看图软件打开:
r

Y轴表示调用栈,X轴越宽,就表示它被抽到的次数多,即执行的时间长。注意,x 轴不代表时间,而是所有的调用栈合并后,按字母顺序排列的。

所以,一般我们只需要看有没有出现 “平顶”,如果有,那么这个函数可能有性能问题。

 
refer:
https://www.jianshu.com/p/675a850365eb
https://www.sohu.com/a/292825608_467784
原文地址:https://www.cnblogs.com/-wenli/p/13784564.html