perf record 和 perf report是一对配套使用的工具,其中,record用来统计,report用来展示。执行record这个命令后,会在当前目录下产生一个 perf.data 文件,接下来就可以使用 perf report 命令来分析这份采样记录了。
常用使用命令
./perf record ./perfdemo
./perf report
测试代码
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#define SIZE 1000000
int cpu_intensive()
{
volatile double sum = 0;
int v = 0;
for (int i = 0; i < SIZE * 2; i++)
{
v = tan(i);
sum += v;
}
return sum;
}
int cpu_test()
{
return cpu_intensive();
}
int main()
{
printf("===== perfdemo =====\n");
while(1)
{
cpu_test();
}
return 0;
}
编译 aarch64-linux-gnu-gcc -g -O0 -fno-omit-frame-pointer -o perfdemo perfdemo.c -lm
命令解析
其中各个字段意义
(1) cycles:ppp 事件
cycles:监控CPU时钟周期(硬件性能计数器)
:ppp 修饰符:
precise(精确):使用PEBS(精确事件采样)技术,减少采样偏差
per-process(进程级):仅统计目标进程的周期
per-core(核心级):不跨CPU核心统计
在record的时候,可以用-e指定记录哪个event。支持哪些event,可以使用pert list查看。
(2) Overhead%
计算公式:(符号的采样数 / 总采样数) * 100%
你的数据示例:
40.21% 表示该地址(0x880)消耗了约40.21%的总CPU周期
结合Event count,可估算绝对耗时:88.75亿 cycles * 40.21% ≈ 35.67亿 cycles
想要查看CPU占用率的话,可以使用-g或 --call-graph记录调用信息
./perf record -g --call-graph fp -e cycles:ppp ./perfdemo
(3) Symbol函数名
正常应该显示函数名称,显示地址可能是没加调试信息无调试符号,也可能跟系统有关。
其中 [.] 表示用户空间函数,[k] 表示内核函数
调试过程
查看内容,CPU占用率最高的是
10.96% perfdemo libm-2.28.so [.] 0x000000000003e3dc
由于系统原因,没有直接打出函数名,所以我们只能通过地址查找是哪个函数接口。根据Shared Objec信息我们可以知道这个接口在libm库里,那我们objdump这个库拿到符号信息。
objdump -D /lib/aarch64-linux-gnu/libm.so.6 > libmdump
打开这个文件,搜索3e3d0地址。可以看到是tan接口,跟代码一致,是占用最多的接口。
objdump perfdemo也能根据0x400578-> 0x4006e8-> 0x4006e8-> 0x400670地址查到调用关系,直至定位到tan接口。
objdump perfdemo -D perfdemo > perfdump