首页 > 技术文章 > 程序代码调优工具perf学习记录

carterzhang 2016-12-15 18:29 原文

perf工具学习记录

简介

1、6.31及后续版本的Linux内核自带工具

2、Perf适用于什么场景

算法优化(空间复杂度、时间复杂度)、代码优化(提到执行速度、减少内存占用) 评估程序对硬件资源的使用情况,例如各级cache的访问次数,各级cache的丢失次数、流水线停顿周期、前端总线访问次数等。 评估程序对操作系统资源的使用情况,系统调用次数、上下文切换次数、任务迁移次数。 3、perf工具的基本原理

a、基于内核,内核版本在 2.6.31之后的都可以进入源码 linux/tool/perf编译安装

b、功能:

perf需要root才能执行,因为他工作在内核级别;
在系统级别对硬件性能数据进行采样,监控CPU/内存等各种性能指标;
特点:无损代码;系统级别;需要硬件和系统支持(cpu指令集等)

c、工作原理:

perf工具是根据事件来进行采样。(事件:程序内部的中断等事件)

具体支持的事件可以用如下命令查看:perf list

主要有三种事件:

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

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

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

监控原理:

perf 会通过系统调用sysperfevent_open在内核中注册一个监测“cycles”事件的性能计数器。内核根据perf 提供的信息在PMU 上初始化一个硬件性能计数器(PMC: Performance Monitoring Counter)。PMC随着CPU 周期的增加而自动累加。在PMC 溢出时,PMU 触发一个PMI(Performance Monitoring Interrupt)中断。内核在PMI 中断的处理函数中保存PMC 的计数值,触发中断时的指令地址(Register IP:Instruction Pointer),当前时间戳以及当前进程的PID,TID,comm 等信息。我们把这些信息统称为一个采样(sample)。内核会将收集到的sample 放入用于跟用户空间通信的Ring Buffer。用户空间里的perf 分析程序采用mmap 机制从ring buffer 中读入采样,并对其解析。perf 根据pid,comm 等信息可以找到对应的进程。根据IP 与ELF 文件中的符号表可以查到触发PMI 中断的指令所在的函数。为了能够使perf 读到函数名,我们的目标程序必须具备符号表。如果读者在perf 的分析结果中只看到一串地

址,而没有对应的函数名时,通常是由于在编译时利用strip 删除了ELF 文件中的符号表。

符号表: readelf –s xxx 可以查看

文件中的"符号表"(symbol table)中所包含的信息用于定位和重定位程序中的符号定义和符号引用;目标文件中的其它部分通过一个符号在这个表中的索引值来使用该符号;索引值从0开始计数,但值为0的索引表项(即第一项)并没有实际的意义,它表示未定义的符号;用常量STN_UNDEF来表示未定义的符号;

通常来讲,字符串、常量变量、函数名等的索引值;在编译时如果用strip则会删除符号表;

typedefstruct {

Elf32_Word st_name;

Elf32_Addr st_value;

Elf32_Word st_size;

unsigned char st_info;

unsigned char st_other;

Elf32_Half st_shndx;

}Elf32_Sym;
示例

基本用法

5、常规用法介绍

a) perf list:列出所有事件类型

b) perf top:类似top的全局监控工具

c) perf stat:对某个程序或者特定进程进行监控

d) perf record & perf report:先记录再通过详细报告的形式打印事件信息

e) Perf timechart:将统计的数据直接显示为矢量图;直观且详细

f) perf diff Read two perf.data files and display the differential profile

6、 PMU/PMI/PMC:

a) PMU:Performance Monitor Unit,性能监视单元,其实CPU提供的一个单元,属于硬件的范畴。通过访问相关的寄存器能读取到CPU的一些性能数据,目前大部分CPU都会提供相应的PMU

b) PMI: Performance Monitoring Interrupt

c) PMC: Performance Monitoring Counter硬件性能计数器

简单实践

7、简单实操:

例子: 10.187.6.97 dwlogudpd2 进程id:480,一般在性能测试用例执行时同步采样;

a、宏观观察,根据pid查看进程宏观表现

task-clock : cpu利用率,在采样时间内,所占用的cpu用于计算,而不是用来做其他事(I/O)的时间的,单位是毫秒;上图为 8785.89974778ms;,倒数第二列为在整个采样时间占得百分比(8785.974778 / 125.592276887*1000),越高越好;

------------ 在采样周期中,pid占用cpu的时间的0.07%为计算时间,其他为cpu等待/切换等耗时;

context-switches:记录进程上下文切换的次数,越少越好;上图,平均值 0.153*106/秒

cpu-migrations:发生了多少次cpu切换,从一个内核切换到另一个内核;

page-faults: 缺页异常

------------ linux内存管理为分页机制, 当应用程序请求的页面尚未建立、请求的页面不在内存中、或者请求的页面虽然在内存中,但尚未建立物理地址与虚拟地址的映射关系时,都会触发一次缺页异常(page‐fault)。内核在捕获缺页异常时,根据异常种类进行相应的处理。

cycles:执行了多少个处理器时钟周期,一个cpu指令可能㤇多个时钟周期(可以从intel/AMD所支持的cpu指令集中查看)

------------ 时钟周期

stalled-cycles-frontend : 我们机器硬件不支持,暂未研究

stalled-cycles-backend :我们机器硬件不支持,暂未研究

instructions :执行了多少个cpu指令

branches:程序在执行期间遇到的分支指令数;

------------- 分支指令:

branch-misses:预测错误的分支指令数;上图 0.49%的分之预测失误率;分之预测失效率越高代表有问题;

-------------- PS:处理器的分支预测机制与OOO机制(Out‐of‐Order):

上面这张图可以看到进程占用的cpu时间大部分并未用来计算,而是用来做其他事情;

b、使用top指定pid进一步查看这个进程都在干什么

上面这张图是一张试试采集数据的累积统计显示图;

------------- 右面第一列为符号名,也就是函数名。
左面第一列为该符号引发的性能事件在整个监测域中占的比例,为该符号的热度。
监测域是指perf 监控的所有符号。默认情况下包括系统中所有进程、内核以及内核模块的函数。
左面第二列为该符号所在的DSO。DSO 即动态共享对象(Dynamic Shared Object)的缩写。
第3 列为DSO 的类型。
perf 中DSO 共有5种类型,分别是:ELF 可执行文件,动态链接库,内核,内核模块,VDSO 等。
当第3列为[.]时表示此符号属于用户态的ELF 文件(包括可执行文件与动态链接库)。
为[k]表示此符号属于内核或内核模。

c、进入对应的函数,看看函数里面在机器底层都在干神马; 下面是选择上图3个进程,前2个为耗时前2名,第三个是dwlogudpd2进程本身函数占用最高的第一名

18.60% [kernel] [k] findbusiestgroup :

Kernel : 说明是系统函数;

findbusiestgroup是linux系统用来内核用来做内核间的负载均衡的其中一个函数,用来找出最忙的内核;位置在:

kernel/sched.c --> loadbalancenewidle()

0.67% dwlogudpd2 [.] boss::EpollReactor::DoWaitForEvents(unsigned int, std::list<int, std::allocator >&)

d、在上图中,选中对应函数,回车进入,选择annotate即可看到下图 以默认性能事件cycles(CPU 周期数)进行的性能剖析,即一个cpu周期中所执行的汇编指令或其他函数统计;

上图可以看到在boss::EpollReactor::DoWaitForEvents函数调用了哪些其他的函数,执行了哪些汇编指令;

   ------------- 内核函数无法查看其内部汇编指令耗时,只有用户进程才可以看得到

callq表示其中调用了其他函数;左边第一列为百分比;第二列为汇编指令或调用其他函数 ,第三列为汇编指令值或函数名;

----------- 从上图可以直观看到对应的热点函数;结合代码即即可进行定位;

perf timechart --- 生成矢量图,但是貌似docker收集不到数据,查资料据说是与glibc库有关。。待实体机进行尝试;

 ------------- 生成的图片类似下面这种,ps,docker生成不了,只是从网上的其它高手的示例图

参考文章

https://perf.wiki.kernel.org/index.php/Main_Page

http://linuxwiki.github.io/PerformanceTools/perf.html

http://www.voidcn.com/blog/mtofum/article/p-1399067.html

http://zhengheng.me/2015/11/12/perf-stat/

http://blog.csdn.net/gengshenghong/article/details/7383438

http://www.ibm.com/developerworks/cn/linux/l-cn-perf1/

http://www.ibm.com/developerworks/cn/linux/l-cn-perf2/

http://wenku.baidu.com/link?url=qc8zgDZnqIHNtHPJSPNWpbwgMpeYro4JYbWxR7pzqxwIMLOqNH7QMWSYvtb7xV2RM-4KLd7e0rZ9Ton1NhLZoYmIuNC4iIrJ2LKYejW

http://www.2cto.com/os/201507/418578.html

http://www.cnblogs.com/vinozly/p/5589032.html

http://blog.csdn.net/21aspnet/article/details/1534304

推荐阅读