perf record/report

Posted Li-Yongjun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了perf record/report相关的知识,希望对你有一定的参考价值。

性能优化

性能优化通常分为两个阶段:性能分析、性能优化

  • 性能分析:查找性能瓶颈、热点代码,分析引发性能问题的原因。
  • 性能优化:基于性能分析,进行性能优化。包括:算法优化(空间复杂度和时间复杂度的权衡)和代码优化(提高执行速度、减少内存占用)。

perf 概述

perf 是 Linux 下的一款性能分析工具,可以用来分析程序中热点函数的 CPU 占用率,从而定位性能瓶颈。
perf 核心功能由 Performance counters(性能计数器) 子系统实现,它提供一个性能分析框架,比如硬件(CPU、PMU(Performance Monitoring Unit))功能和软件(软件计数器、tracepoint)功能。
通过 perf,应用程序可以利用 PMU、tracepoint 和内核中的计数器来进行性能统计。

perf 可以对程序进行函数级和指令级的采样,从而了解程序的性能瓶颈在哪里。
基本原理:在采样时间内,每隔一个固定采样周期,在 CPU 上产生一个中断,看当前是哪个进程、哪个函数在运行,然后就给对应的进程和函数加一个统计值,这样就可以估算出这段采样时间内,CPU 有多少时间花在某个进程和某个函数上。
perf 工具功能非常多,今天我们就来学习最常使用的两个命令:perf record 和 perf report。其中,一个用来统计,一个用来展示。

示例

使用下面这个示例程序,来学习 perf record/report 命令的使用。
perftest.c

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>

void for_loop()

	int i, j;
	int x;

	for (i = 0; i < 1000; i++) 
		for (j = 0; j < 10000; j++) 
			x = sin(i) + cos(j);
		
	


void loop_samll()

	int i;

	for (i = 0; i < 10; i++) 
		for_loop();
	


void loop_big()

	int i;

	for (i = 0; i < 100; i++) 
		for_loop();
	


int main(int argc, char *argv[])


	printf("pid = %d\\n", getpid());
	loop_big();
	loop_samll();

	return EXIT_SUCCESS;

$ gcc -o perftest.out perftest.c -lm
$ ./perftest.out 
pid = 826526

perf record

$ sudo perf record -p 826526 -a -g -F 99 -- sleep 10
Warning:
PID/TID switch overriding SYSTEM
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.082 MB perf.data (991 samples) ]

-p:分析指定进程
-a:对所有 CPU 进行采样
-g:启用调用追溯功能
-F:指定采样频率
-- sleep:采集时长
执行这个命令后,会在当前目录下产生一个 perf.data 文件,接下来就可以使用 perf report 命令来分析这份采样记录了。

perf report

$ sudo perf report


通过 perf report 命令可以展示采样记录,大概介绍下面板参数

  • Samples:采样个数
  • Event count:系统总共发生的事件数
  • Symbol:函数名,其中 [.] 表示用户空间函数,[k] 表示内核函数
  • Shared Objec:函数所在的共享库或所在的程序
  • Command:进程名
  • Self:该函数的 CPU 使用率
  • Children:该函数的子函数的 CPU 使用率

那么,通过示例的展示面板,我们能得到的信息如下:

  • 这次采样,是对 perftest.out 这个进程进行采样
  • 总共采集到了 991 个事件(符合 -F 99 -- sleep 10,即,一秒钟采样 99 次,采样 10 秒钟)
  • 第一行:__libc_start_main 函数,处于用户空间,处于共享库 libc-2.31.so 中,CPU 使用率为 0,其子函数的 CPU 使用率为 47.63%。(因为 __libc_start_main 只调用一次,实际使用 CPU 的都是其子函数)
  • 第二行:main 函数同 __libc_start_main
  • 第三行:loop_big 函数同 __libc_start_main
  • 第四行:__sin_avx 函数,自身 CPU 使用率为 40.36%,子函数 CPU 使用率为 40.36%,说明其没有子函数。
  • 第五行:__cos_avx 函数,CPU 使用率为 38.65%
  • 第六行:for_loop 函数,CPU 使用率 20.99%

通过以上分析,可以知道 CPU 大部分时间都花在执行 sin() 和 cos() 这两个函数上,和示例代码吻合。

以上分析中,有些参数还没理解透彻,后面还会继续对 perf 工具进行学习,逐步增强吧。

以上是关于perf record/report的主要内容,如果未能解决你的问题,请参考以下文章

使用 perf 获取事件计数取决于其他事件的发生

使用atop和perf分析抖动问题的方法

使用atop和perf分析抖动问题的方法

使用atop和perf分析抖动问题的方法

使用atop和perf分析抖动问题的方法

perf stat 前端和后端周期显示大于 100%