
本文梳理一下工作中对perf工具的使用文章开始部分的概念和原理借用了网络上很多不错的文章如有侵权欢迎联系后面笔者争取展示一下在工作中使用perf来解决性能问题的实例。perf概述perf是Linux下的一款性能分析工具能够进行函数级与指令级的热点查找。它由一个叫“Performance counters“的内核子系统实现基于事件采样原理以性能事件为基础支持针对处理器相关性能指标与操作系统相关性能指标的性能剖析可用于性能瓶颈的查找与热点代码的定位。perf原理Perf通过系统调用sys_perf_event_open陷入到内核中内核根据perf提供的信息在PMUPerformance Monitoring Unit上初始化一个硬件性能计数器PMC: Performance Monitoring Counter。PMC随着指定硬件事件的发生而自动累加。在PMC 溢出时PMU触发一个PMIPerformance Monitoring Interrupt中断。内核在PMI 中断的处理函数中保存PMC的计数值触发中断时的指令地址当前时间戳以及当前进程的PID、TID、comm 等信息。我们把这些信息统称为一个采样sample。内核会将收集到的sample放入用于跟用户空间通信的Ring Buffer。用户空间里的perf分析程序采用mmap机制从ring buffer中读入采样并对其解析。perf支持两种模式计算模式和采样模式。后面解释perf stat使用的是计数模式perf record使用的是采样模式。性能事件在程序运行中发生的可能影响到程序性能的软硬件事件使用perf list命令可以显示当前软硬件环境下支持的所有事件大致可以分为三种Hardware Event由PMU部件产生在特定的条件下探测性能事件是否发生以及发生的次数。比如CPU周期、分支指令、TLB重填例外、Cache缺失等。Software Event是内核产生的事件分布在各个功能模块中统计和操作系统相关性能事件。比如系统调用次数、上下文切换次数、任务迁移次数、缺页例外次数等。Tracepoint Event是内核中静态tracepoint所触发的事件这些tracepoint用来判断程序运行期间内核的行为细节比如slab分配器的分配次数等。基于ftrace框架实现内核中的所有tracepoint都可以作为perf都性能事件cat /sys/kernel/debug/tracing/available_events可查看当前系统的所有tracepoint分成了几大类ext4 文件系统的tracepoint events如果是其它文件系统比如XFS也有对应的tracepoint event;jbd2 文件日志的tracepoint events;skb 内存的tracepoint events;net,napi,sock,udp:网络的tracepoint events;scsi, block, writeback 磁盘IOkmem 内存sched 调度syscalls 系统调用性能事件的属性硬件性能事件由处理器中的PMU提供支持。由于现代处理器的主频非常高再加上深度流水线机制从性能事件被触发到处理器响应PMI中断流水线上可能已处理过数百条指令。那么PMI中断采到的指令地址就不再是触发性能事件的那条指令的地址了而且可能具有非常严重的偏差。为了解决这个问题Intel处理器通过PEBS机制实现了高精度事件采样。PEBS通过硬件在计数器溢出时将处理器现场直接保存到内存而不是在响应中断时才保存寄存器现场从而使得perf能够采到真正触发性能事件的那条指令的地址提高了采样精度。在默认条件下perf不使用PEBS机制。用户如果想要使用高精度采样需要在指定性能事件时在事件名后添加后缀”:p”或”:pp”。Perf在采样精度上定义了4个级别如下表所示。级别描述0 无精度保证1 采样指令与触发性能事件的指令之间的偏差为常数:p2 需要尽量保证采样指令与触发性能事件的指令之间的偏差为0:pp3 保证采样指令与触发性能事件的指令之间的偏差必须为0:ppp性能事件的精度级别目前的X86处理器包括Intel处理器与AMD处理器均仅能实现前 3 个精度级别。除了精度级别以外性能事件还具有其它几个属性均可以通过”event:X”的方式予以指定。标志属性u 仅统计用户空间程序触发的性能事件k 仅统计内核触发的性能事件h 仅统计Hypervisor触发的性能事件G 在KVM虚拟机中仅统计Guest系统触发的性能事件H 仅统计 Host 系统触发的性能事件p 精度级别perf常用事件在理解perf常用命令的用法后进一步需要理解的地方就是perf性能调优用的常用事件。理解这些事件更多的是要理解计算机原理、操作系统原理、程序运行机制等一些底层概念才能做到如臂使指。cpu-clocktask-clockcyclesbranch‐misses 分支预测失效的事件CPU-migrations cpu迁移事件page-faults 缺页事件perf常用命令perf共22种子命令常用的是以下5种perf list查看当前软硬件环境支持的性能事件perf stat分析指定程序的性能概况perf top实时显示系统/进程的性能统计信息perf record记录一段时间内系统/进程的性能事件perf report读取perf record生成的perf.data文件并显示分析数据perf stat默认事件简介task-clock任务真正占用的处理器时间单位为ms。CPUs utilized task-clock / time elapsedCPU的占用率值高说明程序的多数时间花费在CPU计算上而非IO。context-switches上下文的切换次数。CPU-migrations处理器迁移次数。Linux为了维持多个处理器的负载均衡在特定条件下会将某个任务从一个CPU迁移到另一个CPU。page-faults缺页异常的次数。当应用程序请求的页面尚未建立、请求的页面不在内存中或者请求的页面虽然在内存中但物理地址和虚拟地址的映射关系尚未建立时都会触发一次缺页异常。另外TLB不命中页面访问权限不匹配等情况也会触发缺页异常。cycles消耗的处理器周期数。instructions执行了多少条指令。IPC为平均每个cpu cycle执行了多少条。branches遇到的分支指令数。branch-misses预测错误的分支指令数。perf stat参数-e event指定性能事件可以是多个用,分隔列表-p pid指定待分析进程的 pid可以是多个用,分隔列表-t tid;指定待分析线程的 tid可以是多个用,分隔列表-a从所有 CPU 收集系统数据-d打印更详细的信息可重复 3 次-dL1 和 LLC data cache-d -ddTLB 和 iTLB events-d -d -d增加 prefetch events-r n;重复运行命令 n 次打印平均值。n 设为 0 时无限循环打印-c cpu-list只统计指定 CPU 列表的数据如0,1,3或1-2-A与-a选项联用不要将 CPU 计数聚合-I N msecs每隔 N 毫秒打印一次计数器的变化N 最小值为 100 毫秒perf top常用命令行参数-e event指明要分析的性能事件。-p pid仅分析目标进程及其创建的线程。-k path带符号表的内核映像所在的路径。-K不显示属于内核或模块的符号。-U不显示属于用户态程序的符号。-d n界面的刷新周期默认为2s。-g得到函数的调用关系图perf record收集一段时间内的性能事件到文件 perf.data随后需要用perf report命令分析。-e event指定性能事件可以是多个用,分隔列表-p pid指定待分析进程的 pid可以是多个用,分隔列表-t tid指定待分析线程的 tid可以是多个用,分隔列表-u uid指定收集的用户数据uid为名称或数字-a从所有 CPU 收集系统数据-g开启 call-graph (stack chain/backtrace) 记录-C cpu-list只统计指定 CPU 列表的数据如0,1,3或1-2-r RT priorityperf 程序以SCHED_FIFO实时优先级RT priority运行这里填入的数值越大进程优先级越高即 nice 值越小-c count 事件每发生 count 次采一次样-F n每秒采样 n 次-o output.data指定输出文件output.data默认输出到perf.dataperf应用案例对于一种工具首先要知道它能用来做什么的然后要知道怎么去用它。像perf这样功能强大的性能分析工具聪明人可能找出问题点一条命令即可找到程序热点但对于不那么聪明但人我还是需要想办法形成一套方法但或者说是形成一种套路最好能做到有条有理循序渐进慢慢逼近问题的真相。分析和调查Linux上的各种性能问题需要我们对Linux内核有比较多的了解不然恐怕是无从下手的。perf stat获取基准性能分析的第一步是要获取一个基准性能后面所有的优化都和这个基准性能做对比。不要忘记编译器的优化选项很多时候使用编译器的优化就足以解决性能问题。cpu-clock事件正是此步需要的它以毫秒为单位显示cpu时钟事件的数量以及执行时间。It displays the number of cpu-clock events in milliseconds and the elapsed execution time. These times are the baseline for future comparisons.利用perf性能调优时需要回答3个问题程序的哪一部分耗用了最多的时间Which parts of the program take the most execution time?程序占用时间最多的部分称为“热点”。对热点进行优化分析是最有价值的有可能很小的改动得到意想不到的效果。软/硬件性能事件的数量就代表需要实际修正的问题吗Do the number of software or hardware events indicate an actual performance issue to be fixed?要回答这个问题我们需要对程序中的算法和数据结构有一定的了解或直觉。了解程序的类型是cpu密集性、memory密集性、io密集性然后在针对热点位置具体分析。如何修正这些性能问题How can we fix the performance issue?我们需要研究程序的算法和数据结构找到其中不合理的地方修改代码然后观察效果。性能调优是一项艰巨的实验工作如果修改后的程序运行速度低于基准速度请不要感到惊讶。如果一个假设失败则尝试另一个。继续尝试参考资料Linux kernel profiling with perfPERF tutorial: Finding execution hot spotsPerf -- Linux下的系统性能调优工具第 1 部分perf 火焰图分析程序性能Perf介绍在Linux下做性能分析3perfperf 性能分析实例——使用perf优化cache利用率Perf深度解析perfperf stat输出解读