作为做事器后台开拓,不仅仅要写业务逻辑,后台意味着高并发,稳定性,当你写了很多逻辑,创造性能有问题的时候,也要学会性能剖析,进行性能优化, 大概你会打仗很多性能剖析工具:valgrind,gperftools,gprof, oprofile, 有韶光逐步逐一先容,在学习perf的过程中,也学习和加深了很多之前的知识,本文抛砖引玉,希望能帮助大家理解一些性能剖析更深的一些东西。
1. perf简介perf是一款linux内置的性能剖析工具,随着内核发布,也被称为perf_events, perf tools, PCL(Performance Counters for Linux), 发布于Linux kernel version 2.6.31, perf是怎么事情的呢?perf如何利用?本文是来先容一下。
perf官方wiki的先容是:Linux profiling with performance counters

Perf可以办理高等性能和故障打消,它可以剖析(当然目前我也只是用来进行cpu性能剖析):
为什么内核花费CPU高, 代码的位置在哪里?什么代码引起了CPU 2级cache未命中?CPU是否花费在内存I/O上?哪些代码分配内存,分配了多少?什么触发了TCP重传?某个内核函数是否正在被调用,调用频率多少?线程开释CPU的缘故原由?2. perf的event它可以利用CPU performance counters(性能计数器),tracepoints, kprobes和uprobes来进行运用程序的性能剖析。perf利用这些linux内核供应的tracing特性进行事宜的采集和剖析,perf利用的event紧张有以下几种:
Hardware Events: CPU中的寄存器含有performance counters(性能计数器),用来统计 Hardware event,例如 cpu-cycles、instructions executed 、cache-misses、branch mispredicted等。这些event构成了运用程序profiling的根本。Software Events: 基于内核计数器的低优先级events, 例如, CPU migrations(处理器迁移次数), minor faults(soft page faults), major faults(hard page faults).Tracepoints: 是散落在内核源代码中的一些 hook,用来调用probe函数,开启后,它们便可以在特定的代码被运行到时被触发,这一特性可以被各种 trace/debug 工具所利用。Perf 便是该特性的用户之一。如果您想知道在运用程序运行期间,内核内存管理模块的行为,便可以利用潜伏在 slab 分配器中的 tracepoint。当内核运行到这些 tracepoint 时,便会关照 perf。Dynamic Tracing: probe函数(探针or探测函数),kprobe(kernel probe)内核态探针,用来创建和管理内核代码中的探测点。Uprobes,user-probe,用户态探针,用来对用户态运用程序进行探测点的创建和管理,关于kprobe和uprobe可参考对应的内核文档perf利用的event来源,如下图:来源:brendangregg3. 安装两种安装办法
通过包管理进行安装,perf工具在 linux-tools-common工具包里,通过包管理软件安装的时候还须要依赖linux-tools-kernelversion包源码编译:找到对应内核版本的源码包,在tools/perf目录下进行编译4. 背景要想利用perf来剖析运用程序,须要理解一些根本观点,例如符号表, frame pointer等信息
4.1 符号表
运用程序的符号表,用来将逻辑地址翻译成对应的函数和变量名,这样才能被程序员阅读和剖析,没有符号表,profile的结果都是一些16进制的逻辑地址:
如下是perf report剖析sshd进程的堆栈调用情形(来自brendangregg):
对付通过软件包安装的程序,常日都会有dubug package(-dbgsym)即带有符号表信息的程序,如果是源码安装的就须要编译时开启debug选项。
通过利用openssh-server-dbgsym and libc6-dbgsym,sshd的perf report剖析结果如下:
4.2 栈回溯(栈展开)
我们常常在编译的时候会开启frame pointers优化选项,即优化掉函数栈帧rbp,省略掉frame pointer是编译器一个很烂的优化,它会毁坏debug, 更烂的是省略frame pointer一样平常是编译器默认的优化选项。
没有frame pointer会使perf 无法获取完全的调用栈,如下示例:
例如上面代码正常不开启优化的编译,进行profile是可以看到call graph的,如下:
如果编译时开启-fomit-frame-pointer(这里由于测试代码大略,直接开优化的话就优化没了),就无法获取到call graph
有三种方法可以修复这个问题,这里不做展开,这些stack walking techniques后面可以写一篇单独的文章:
using dwarf data to unwind the stack, 实际上很多profile工具:gperftools, valgrind都是依赖于libunwind,通过dwarf来进行stack trace的using last branch record (LBR) if available (a processor feature)returning the frame pointers5. 利用perf供应了一系列的命令来剖析程序,如下:
sub command功能解释
annotate 读取perf.data(由perf record天生)显示注释信息,如果被剖析的进程含义debug符号信息,则会显示汇编和对应的源码,否则只显示汇编代码
archive 根据perf.data(由perf record天生)文件中的build-id将干系的目标文件打包,方便在其他机器剖析
bench perf供应的基准套件的通用框架,可以对当前系统的调度,IPC,内存访问进行性能评估
buildid-cache 管理build-id,管理对付的bin文件
buildid-list 列出perf.data中的以是buildids
data 把perf.data文件转换成其他格式diff读取多个perf.data文件,并给出差异剖析
evlist 列出perf.data中采集的事宜列表
kmem 剖析内核内存的利用kvm剖析
kvm 虚拟机上的guest os
list 列出当前系统支持的所有事宜名,可分为三类:硬件事宜、软件事宜,检讨点
lock 剖析内核中的锁信息,包括锁的争用情形,等待延迟等
record 对程序运行过程中的事宜进行剖析和记录,并写入perf.data
report 读取perf.data(由perf record天生) 并显示剖析结果
sched 针对调度器子系统的剖析工具。
script 读取perf.data(由perf record天生),天生trace记录,供其他剖析工具利用
stat 对程序运行过程中的性能计数器进行统计
test perf对当前软硬件平台进行健全性测试,可用此工具测试当前的软硬件平台是否能支持perf的所有功能。
timechart 对record结果进行可视化剖析输出,record命令须要加上timechart记录
top 对系统的性能进行剖析,类型top命令,当然可以对单个进程进行剖析
probe 用于定义动态检讨点。
trace 类似于strace,跟踪目标的系统调用,但开销比strace小
perf的利用大体可以有三种办法:
Counting:统计的办法,统计事宜发生的次数,这种办法不天生perf.data文件,例如perf stat, perf topSampling:采样的办法,采样事宜,并写入到内核buffer中,并异步写入perf.data文件中,perf.data文件可以被perf report或者perf script 命令读取。bpf programs on events(https://www.ibm.com/developerworks/cn/linux/l-lo-eBPF-history/index.html)5.1. perf list
perf list命令可以列出当前perf可用的事宜:
cpu-cycles OR cycles [Hardware event]instructions [Hardware event]cache-references [Hardware event]cache-misses [Hardware event]branch-instructions OR branches [Hardware event]branch-misses [Hardware event]bus-cycles [Hardware event]stalled-cycles-frontend OR idle-cycles-frontend [Hardware event]stalled-cycles-backend OR idle-cycles-backend [Hardware event]ref-cycles [Hardware event]alignment-faults [Software event]bpf-output [Software event]context-switches OR cs [Software event]cpu-clock [Software event]cpu-migrations OR migrations [Software event]dummy [Software event]emulation-faults [Software event]major-faults [Software event]minor-faults [Software event]page-faults OR faults [Software event]task-clock [Software event]msr/tsc/ [Kernel PMU event]rNNN [Raw hardware event descriptor]cpu/t1=v1[,t2=v2,t3 ...]/modifier [Raw hardware event descriptor](see 'man perf-list' on how to encode it)mem:<addr>[/len][:access] [Hardware breakpoint]
这些事宜可以分为三类(在文章开始先容perf事情事理的时候也说了):Hardware Event, Software event, Tracepoint event.
每个详细事宜的含义在perf_event_open的man page中有解释:
cpu-cycles:统计cpu周期数,cpu周期:指一条指令的操作韶光。instructions: 机器指令数目cache-references: cache命中次数cache-misses: cache失落效次数branch-instructions: 分支预测成功次数branch-misses: 分支预测失落败次数alignment-faults: 统计内存对齐缺点发生的次数, 当访问的非对齐的内存地址时,内核会进行处理,已保存不会发生问题,但会降落性能context-switches: 高下文切换次数,cpu-clock: cpu clock的统计,每个cpu都有一个高精度定时器task-clock :cpu clock中有task运行的统计cpu-migrations:进程运行过程中从一个cpu迁移到另一cpu的次数page-faults: 页缺点的统计major-faults:页缺点,内存页已经被swap到硬盘上,须要I/O换回minor-faults :页缺点,内存页在物理内存中,只是没有和逻辑页进行映射5.2. perf stat
perf stat可以对程序运行过程中的性能计数器(包括Hardware,software counters)进行统计,剖析程序的整体花费情形:
$perf stat lsPerformance counter stats for 'ls': 2.164836 task-clock (msec) # 0.808 CPUs utilized 51 context-switches # 0.024 M/sec 4 cpu-migrations # 0.002 M/sec 333 page-faults # 0.154 M/sec 5506056 # 2.543 GHz 0 stalled-cycles-frontend # 0.00% frontend cycles idle 0 stalled-cycles-backend # 0.00% backend cycles idle 6100570 instructions # 1.11 insns per cycle 1298744 branches # 599.927 M/sec 18509 branch-misses # 1.43% of all branches 0.002679758 seconds time elapsed
详细各个字段的含义在perf list中已经列出了,这里剖析一下主要的数据:
task-clock (msec): cpu处理task所花费的韶光,单位ms,0.808 CPUs utilized的表示cpu利用率为80.8% = 2.164836 / 2.679758. 该值越高代表程序是CPU bound而非IO bound 类型。instructions:实行的指令条数, insns per cycle: 即IPC,每个cpu周期实行的指令条数,1.11 = 6100570(instructions) / 5506056(cycles),IPC比上面的CPU利用率更能解释CPU的利用情形,关于IPC有一篇brendangregg的文章,很好的解释CPU利用率不是一个很好的性能剖析指标stalled-cycles-frontend和stalled-cycles-backend表示CPU结束统计,详细可参考perf stat可以加上-e选项来设置自己关心的事宜统计,详细参数可以通过上面的perf list来查看
5.3. perf top
perf top类似系统的命令top,可以实时的查看当前系统各个进程的各个函数的性能计数剖析:$sudo perf top
perf top的和perf record的功能参数差不多,我们可以加上-e:来统计特定的event,-g: 开启call-graph, -p:剖析特定的进程
平常我们用的更多的是perf record,由于它可以将profiler的结果输出到文件,然后通过perf report来进行剖析,或者通过可视化工具进行剖析和输出。以是下面着重先容perf record
5.4. perf record
perf reord可以运行一个命令,但更多的是对已运行的进程进行性能剖析,并将剖析结果输出到perf.data(默认该文件名)中。不会像perf top一样实时输出剖析结果。输出perf.data可以通过perf report进行剖析,或者通过perf script输出结果给第三方输出可视化的视图。用前面的示例代码进行测试如下:
$perf record -g -F 99 ./a.out$perf report
perf record几个总要参数解释一下:
-F: 事宜采样的频率, 单位HZ, 更高的频率会得到更细的统计,但会带来更多的开销-g: 进行堆栈追踪,天生调用关系图,等价于–call-graph, 默认情形下,-g等同于–call-graph fp,即通过frame pointer来进行堆栈追踪。 如果frame pointer被优化掉的话,可以通过dwarf, lbr进行堆栈追踪sleep: 采样的韶光5.5. perf可视化剖析
perf 供应了内置的可视化剖析工具 perf timechart,例如:
$perf timechart record ./a.out$perf timechart
perf timechart输出的是进程运行过程中系统调度的情形,无法对程序的详细代码段进行性能剖析,但可以看出总结运行情形:running,idle,I/O等,
Brendangregg写了两款对perf采样结果进行可视化剖析的开源工具:Flame Graphs和HeatMap. FlameGraphs即所谓的火焰图,是大家利用比较多的工具,能清晰的展示程序各个函数的性能花费。HeatMap可以从采样数据中的延迟数据来进行花费展示。
下面是对之前实例代码的采样数据perf.data进行FlameGraphs的绘制:
$perf script |./stackcollapse-perf.pl|./flamegraph.pl > fg_output.svg
perf_flamegraph.png
6. 参考Perf官方wiki
https://perf.wiki.kernel.org/index.php/Main_Page
Perf 维基百科
https://en.wikipedia.org/wiki/Perf_(Linux)
Perf – Linux下的系统性能调优工具,第 1 部分
https://www.ibm.com/developerworks/cn/linux/l-cn-perf1/index.html
Linux 效能剖析工具: Perf
http://wiki.csie.ncku.edu.tw/embedded/perf-tutorial
Linux内核调试技能——kprobe利用与实现
https://blog.csdn.net/luckyapple1028/article/details/52972315
内核uprobes利用先容
https://blog.csdn.net/badu_123/article/details/8302642
perf Examples
http://www.brendangregg.com/perf.html
火焰图的利用
http://www.brendangregg.com/flamegraphs.html
https://github.com/brendangregg/FlameGraph
页缺点
https://yq.aliyun.com/articles/55820
http://cwndmiao.github.io/programming%20tools/2013/11/26/Dwarf/