首页 » 网站建设 » PHP火焰图技巧_调试perf和火焰图

PHP火焰图技巧_调试perf和火焰图

访客 2024-12-06 0

扫一扫用手机浏览

文章目录 [+]

perf可以统计或采样的event有很多,如果我们要剖析cpu,那么我们可以利用cpu-cycles、cpu-clock来衡量占用cpu的程序的分布情形,还可以通过cache-misses、page-faults、branch-misses等event来剖析造成cpu占用高的底层缘故原由,确定缘故原由后方便优化。

如果我们要剖析内存、io、网络等,也可以通过其他event来进行剖析,perf可以利用的event非常多,如果要利用perf来剖析问题,就须要理解问题干系的event有哪些,浸染是什么,这是利用perf的一个门槛。

PHP火焰图技巧_调试perf和火焰图

perf事情大致可以分成三种模式:

PHP火焰图技巧_调试perf和火焰图
(图片来自网络侵删)
counter 计数模式,记录perf实行过程中,统计的目标程序或者全体系统范围内,event的涌现次数。
sampling 采样模式,按照指定频率去采样event,记录每次采样时,采样事宜输出的信息(cpu、进程id、运行栈等)。
这种办法由于每次都记录信息,以是额外的资源花费是比较大的,须要权衡一下采样频率。
同时产生的数据量也随意马虎很大,可能须要大量的硬盘空间。
bpf 可以对对应的event实行用户自己设计的代码,也便是说记录的信息、实行的操作可以由用户定制

perf可以利用的event非常多,上图是Brendan Gregg的文章中找到的一张图,画出了perf可以利用的event的构造图,大致可以分为以下几类:

Hardware Events: CPU的PMU(performance monitoring unit)触发的事宜,也叫performance monitoring counters (PMCs),例如cpu-cycles、cache missSoftware Events: 一些比较底层的软件event,例如缺页、timer(定时)Kernel Tracepoint Events: 内核中的tracepointUser Statically-Defined Tracing (USDT): 用户态的tracepointDynamic Tracing: 动态设置的event,例如利用内核的kprobe,可以在大部分函数动态增加eventTimed Profiling: 定时event安装x86安装

sudo apt install linux-tools-commonsudo apt install linux-tools-genericsudo apt install linux-tools-5.4.0-137-generic 交叉编译

由于我们常常是在自己编译的内核上进行开拓事情,进入linux内核源码目录linux/tools/perf。

➜ tools git:(firefly) ✗ make CROSS_COMPILE=/home/zhongyi/code/rk3399_linux_release_v2.5.1_20210301/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- ARCH=arm WERROR=0 perf V=1

可能在编译的时候,有报错大概是由于平台问题,数据类型不匹配,导致所有的warning都被当作error对待:涌现这问题的缘故原由是-Werror这个gcc编译选项。
只要在makefile中找到包含这个-Werror选项的句子,将-Werror删除,或是注释掉就行了

编译完成后将会在当前目录下天生perf可实行文件,拷贝到设备上即可运行。

root@firefly:~/mnt# ./perf --help usage: perf [--version] [--help] [OPTIONS] COMMAND [ARGS] The most commonly used perf commands are: annotate Read perf.data (created by perf record) and display annotated code archive Create archive with object files with build-ids found in perf.data file bench General framework for benchmark suites buildid-cache Manage build-id cache. buildid-list List the buildids in a perf.data file data Data file related processing diff Read perf.data files and display the differential profile evlist List the event names in a perf.data file inject Filter to augment the events stream with additional information kmem Tool to trace/measure kernel memory properties kvm Tool to trace/measure kvm guest os list List all symbolic event types lock Analyze lock events mem Profile memory accesses record Run a command and record its profile into perf.data report Read perf.data (created by perf record) and display the profile sched Tool to trace/measure scheduler properties (latencies) script Read perf.data (created by perf record) and display trace output stat Run a command and gather performance counter statistics test Runs sanity tests. timechart Tool to visualize total system behavior during a workload top System profiling tool. trace strace inspired tool See 'perf help COMMAND' for more information on a specific command.利用方法总览

上图整理了perf的子命令之间的关系,常用的有:

perf record —— 采样,天生perf.data二进制文件perf annotate/perf report/perf script —— 剖析perf.data文件,annotate可以查看代码,report可以统计剖析,script是直接转化成文本格式perf stat —— counter,统计event的涌现次数perf top —— 全体系统的剖析,类似于top命令,但可以详细到函数,可以指定event

下面我们先容一些常用的利用方法。

help

perf --help之后可以看到perf的一级命令。

root@firefly:~/mnt# ./perf --help usage: perf [--version] [--help] [OPTIONS] COMMAND [ARGS] The most commonly used perf commands are: annotate Read perf.data (created by perf record) and display annotated code archive Create archive with object files with build-ids found in perf.data file bench General framework for benchmark suites buildid-cache Manage build-id cache. buildid-list List the buildids in a perf.data file data Data file related processing diff Read perf.data files and display the differential profile evlist List the event names in a perf.data file inject Filter to augment the events stream with additional information kmem Tool to trace/measure kernel memory properties kvm Tool to trace/measure kvm guest os list List all symbolic event types lock Analyze lock events mem Profile memory accesses record Run a command and record its profile into perf.data report Read perf.data (created by perf record) and display the profile sched Tool to trace/measure scheduler properties (latencies) script Read perf.data (created by perf record) and display trace output stat Run a command and gather performance counter statistics test Runs sanity tests. timechart Tool to visualize total system behavior during a workload top System profiling tool. trace strace inspired tool See 'perf help COMMAND' for more information on a specific command.

perf command --help 可以看到二级命令的帮助命令。

root@firefly:~/mnt# ./perf stat -h Usage: perf stat [<options>] [<command>] -a, --all-cpus system-wide collection from all CPUs -A, --no-aggr disable CPU count aggregation -B, --big-num print large numbers with thousands' separators -C, --cpu <cpu> list of cpus to monitor in system-wide -c, --scale scale/normalize counters -D, --delay <n> ms to wait before starting measurement after program s -d, --detailed detailed run - start a lot of events -e, --event <event> event selector. use 'perf list' to list available even -G, --cgroup <name> monitor event in cgroup name only -g, --group put the counters into a counter group -I, --interval-print <n> print counts at regular interval in ms (>= 10) -i, --no-inherit child tasks do not inherit counters -n, --null null run - dont start any counters -o, --output <file> output file name -p, --pid <pid> stat events on existing process id -r, --repeat <n> repeat command and print average + stddev (max: 100, f -S, --sync call sync() before starting a run -t, --tid <tid> stat events on existing thread id -T, --transaction hardware transaction statistics

下面对一级命令作一个阐明

序号 命令 浸染 1 annotate 解析perf record天生的perf.data文件,显示被注释的代码。
2 archive 根据数据文件记录的build-id,将所有被采样到的elf文件打包。
利用此压缩包,可以再任何机器上剖析数据文件中记录的采样数据。
3 bench perf中内置的benchmark,目前包括两套针对调度器和内存管理子系统的benchmark。
4 buildid-cache 管理perf的buildid缓存,每个elf文件都有一个独一无二的buildid。
buildid被perf用来关联性能数据与elf文件。
5 buildid-list 列出数据文件中记录的所有buildid。
6 diff 比拟两个数据文件的差异。
能够给出每个符号(函数)在热点剖析上的详细差异。
7 evlist 列出数据文件perf.data中所有性能事宜。
8 inject 该工具读取perf record工具记录的事宜流,并将其定向到标准输出。
在被剖析代码中的任何一点,都可以向事宜流中注入其它事宜。
9 kmem 针对内核内存(slab)子系统进行追踪丈量的工具 10 kvm 用来追踪测试运行在KVM虚拟机上的Guest OS。
11 list 列出当前系统支持的所有性能事宜。
包括硬件性能事宜、软件性能事宜以及检讨点。
12 lock 剖析内核中的锁信息,包括锁的争用情形,等待延迟等。
13 mem 内存存取情形 14 record 网络采样信息,并将其记录在数据文件中。
随后可通过其它工具对数据文件进行剖析。
15 report 读取perf record创建的数据文件,并给出热点剖析结果。
16 sched 针对调度器子系统的剖析工具。
17 script 实行perl或python写的功能扩展脚本、天生脚本框架、读取数据文件中的数据信息等。
18 stat 实行某个命令,网络特定进程的性能概况,包括CPI、Cache丢失率等。
19 test perf对当前软硬件平台进行健全性测试,可用此工具测试当前的软硬件平台是否能支持perf的所有功能。
20 timechart 针对测试期间系统行为进行可视化的工具 21 top 类似于linux的top命令,对系统性能进行实时剖析。
22 trace 关于syscall的工具。
23 probe 用于定义动态检讨点。

全局性概况:

perf list查看当前系统支持的性能事宜;

perf bench对系统性能进行摸底;

perf test对系统进行健全性测试;

perf stat对全局性能进行统计;

全局细节:

perf top可以实时查看当前系统进程函数占用率情形;

perf probe可以自定义动态事宜;

特定功能剖析:

perf kmem针对slab子系统性能剖析;

perf kvm针对kvm虚拟化剖析;

perf lock剖析锁性能;

perf mem剖析内存slab性能;

perf sched剖析内核调度器性能;

perf trace记录系统调用轨迹;

最常用功能perf record,可以系统全局,也可以详细到某个进程,愈甚详细到某一进程某一事宜;可宏不雅观,也可以很微不雅观。

pref record记录信息到perf.data;

perf report天生报告;

perf diff对两个记录进行diff;

perf evlist列出记录的性能事宜;

perf annotate显示perf.data函数代码;

perf archive将干系符号打包,方便在其它机器进行剖析;

perf script将perf.data输出可读性文本;

可视化工具perf timechart

perf timechart record记录事宜;

perf timechart天生output.svg文档;

list

利用perf之前肯定要知道perf能监控哪些性能指标吧?那么就要利用perf list进行查看,常日利用的指标是cpu-clock/task-clock等,详细要根据须要来判断。

root@firefly:~/mnt# perf listList of pre-defined events (to be used in -e): rNNN [Raw hardware event descrip cpu/t1=v1[,t2=v2,t3 ...]/modifier [Raw hardware event descrip (see 'man perf-list' on how to encode it) mem:<addr>[/len][:access] [Hardware breakpoint] android_fs:android_fs_dataread_end [Tracepoint event] android_fs:android_fs_dataread_start [Tracepoint event] android_fs:android_fs_datawrite_end [Tracepoint event] android_fs:android_fs_datawrite_start [Tracepoint event] asoc:snd_soc_bias_level_done [Tracepoint event] asoc:snd_soc_bias_level_start [Tracepoint event] asoc:snd_soc_dapm_connected [Tracepoint event] asoc:snd_soc_dapm_done [Tracepoint event] asoc:snd_soc_dapm_path [Tracepoint event] asoc:snd_soc_dapm_start [Tracepoint event] asoc:snd_soc_dapm_walk_done [Tracepoint event] asoc:snd_soc_dapm_widget_event_done [Tracepoint event] asoc:snd_soc_dapm_widget_event_start [Tracepoint event] asoc:snd_soc_dapm_widget_power [Tracepoint event] asoc:snd_soc_jack_irq [Tracepoint event] asoc:snd_soc_jack_notify [Tracepoint event] asoc:snd_soc_jack_report [Tracepoint event] block:block_bio_backmerge [Tracepoint event] block:block_bio_bounce [Tracepoint event] block:block_bio_complete [Tracepoint event] block:block_bio_frontmerge [Tracepoint event] block:block_bio_queue [Tracepoint event] block:block_bio_remap [Tracepoint event] block:block_dirty_buffer [Tracepoint event] block:block_getrq [Tracepoint event] ......

详细监控哪个变量的话,譬如利用后面的perf report工具,则加-e 监控指标,如监控运行ls命令时的cpu时钟占用:

perf report -e cpu-clock lsevent

不同内核版本列出的结果不一样多。
不过基本是够用的,但是无论多少,我们可以基本将其分为三类

一些事宜只是纯挚的内核计数器,这种情形下,他们被称为software events。
例如,高下文切换。
事宜的另一个来源是处理器本身及其性能监控单元(Performance Monitoring Unit,PMU)。
它供应了一个事宜列表来衡量微架构事宜,如周期数、指令非常、L1缓存未命中等。
这些事宜被称为PMU硬件事宜( PMU hardware events)或简称为硬件事宜(hardware events)。
这些事宜因每种处理器类型和型号而异。
perf_events接口还供应了一小组常见的硬件事宜名字工具。
在每个处理器上,这些事宜被映射到CPU供应的实际事宜上,只有映射成立即实际事宜存在时,这些事宜才能被利用。
这些事宜也被称为硬件事宜(hardware events)和硬件缓存事宜( hardware cache events)。
还有一些 tracepoint events 是依赖于ftrace架构实现的,这些只有在2.6.3x以上的内核才可以利用。

一个事宜可以有子事宜(或 unit masks)。
在某些处理器上,对付某些事宜,可以将 unit masks组合 利用并丈量任一子事宜发生的韶光。

/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: 系统调用属性

用户如果想要利用高精度采样,须要在指定性能事宜时,在事宜名后添加后缀:p或:pp。
Perf在采样精度上定义了4个级别,如下所示。

0 :无精度担保1 :采样指令与触发性能事宜的指令之间的偏差为常数(:p)2 :须要只管即便担保采样指令与触发性能事宜的指令之间的偏差为0(:pp)3 :担保采样指令与触发性能事宜的指令之间的偏差必须为0(:ppp)

目前的X86处理器,包括Intel处理器与AMD处理器均仅能实现前 3 个精度级别。

除了精度级别以外,性能事宜还具有其它几个属性,均可以通过event:X的办法予以指定。

u 仅统计用户空间程序触发的性能事宜k 仅统计内核触发的性能事宜h 仅统计Hypervisor触发的性能事宜G 在KVM虚拟机中,仅统计Guest系统触发的性能事宜H 仅统计 Host 系统触发的性能事宜p 精度级别stat

perf stat 剖析系统/进程的整体性能概况。

命令解析

-a, --all-cpus 采集所有CPU的信息-A, --no-aggr 不要在system-wide(-a)模式下搜集所有CPU的计数信息-B, --big-num 保留三位小数-C, --cpu <cpu> 指定某个cpu-D, --delay <n> 在测试程序开始后,在丈量前等等 n ms-d, --detailed 打印更详细的统计数据,最多可以指定3次 -d: detailed events, L1 and LLC data cache -d -d: more detailed events, dTLB and iTLB events -d -d -d: very detailed events, adding prefetch events -e, --event <event> 事宜选择。
可以参考perf list。
-G, --cgroup <name> 仅在name为cgroup时有效。
-g, --group 将计数器放到一个计数组中 -I, --interval-print <n> 每n毫秒打印计数增量(最小值:10ms).在某些情形下,开销可能很高,例如小于100毫秒的间隔。
-i, --no-inherit 禁止子任务继续父任务的性能计数器。
-M, --metrics <metric/metric group list> 监视指定的 metrics 或 metric groups,以逗号分隔。
-n, --null 仅输出目标程序的实行韶光,而不开启任何性能计数器。
-o, --output <file> 输出文件的名字-p, --pid <pid> 指定待剖析的进程id-r, --repeat <n> 重复实行 n 次目标程序,并给出性能指标在n 次实行中的变革范围。
-S, --sync 在开始前调用sync() -t, --tid <tid> 指定待剖析的线程id-T, --transaction 如果支持,打印事务实行的统计数据。
-v, --verbose 显示详细信息-x, --field-separator <separator> 利用CSV样式的输出打印计数,以便直接导入表格。
列由SEP中指定的字符串分隔。
举例

ubuntu# perf stat -B dd if=/dev/zero of=/dev/null count=10000001000000+0 records in1000000+0 records out512000000 bytes (512 MB, 488 MiB) copied, 0.868718 s, 589 MB/s Performance counter stats for 'dd if=/dev/zero of=/dev/null count=1000000': 869.31 msec task-clock # 0.999 CPUs utilized 2 context-switches # 0.002 K/sec 0 cpu-migrations # 0.000 K/sec 71 page-faults # 0.082 K/sec <not supported> cycles <not supported> instructions <not supported> branches <not supported> branch-misses 0.870022180 seconds time elapsed 0.450870000 seconds user 0.418950000 seconds sys

如果没有指定那个事宜,perf stat将网络上面列出的常见事宜。
比如,高下文切换,CPU迁移次数,缺页故障等。

task‐clock:事宜表示目标任务真正占用途理器的韶光,单位是毫秒。
也称任务实行韶光。
CPUs utilized = task-clock / time elapsed,CPU的占用率。
context-switches:程序在运行过程中高下文的切换次数。
CPU-migrations:程序在运行过程中发生的处理器迁移次数。
Linux为了坚持多个处理器的负载均衡,在特定条件下会将某个任务从一个CPU迁移到另一个CPU。
CPU迁移和高下文切换:发生高下文切换不一定会发生CPU迁移,而发生CPU迁移时肯定会发生高下文切换。
发生高下文切换有可能只是把高下文从当前CPU中换出,下一次调度器还是将进程安排在这个CPU上实行。
page-faults:缺页非常的次数。
当运用程序要求的页面尚未建立、要求的页面不在内存中,或者要求的页面虽然在内存中,但物理地址和虚拟地址的映射关系尚未建立时,都会触发一次缺页非常。
其余TLB不命中,页面访问权限不匹配等情形也会触发缺页非常。
cycles:花费的处理器周期数。
如果把被ls利用的cpu cycles算作是一个处理器的,那么它的主频为2.486GHz。
可以用cycles / task-clock算出。
stalled-cycles-frontend:指令读取或解码的质量步骤,未能按空想状态发挥并行旁边,发生结束的时钟周期。
stalled-cycles-backend:指令实行步骤,发生结束的时钟周期。
instructions:实行了多少条指令。
IPC为均匀每个cpu cycle实行了多少条指令。
branches:碰着的分支指令数。
branch-misses是预测缺点的分支指令数。
branch‐misses:是预测缺点的分支指令数。
XXX seconds time elapsed:系程序持续韶光

每次运行性能工具时,可以丈量一个或多个事宜。
事宜利用其符号名称,后跟可选的单元掩码和润色符来指定。
事宜名称、单元掩码和润色符不区分大小写。

perf stat -e cpu-clock dd if=/dev/zero of=/dev/null count=100000

默认情形下,会在用户和内核级别丈量事宜。
如果仅在用户级别进行丈量,须要通报一个润色符:

perf stat -e cpu-clock:u dd if=/dev/zero of=/dev/null count=100000

如果即在用户态丈量,又在内核态丈量,则可以同时通报uk参数

perf stat -e cpu-clock:uk dd if=/dev/zero of=/dev/null count=100000

ls命令实行了多少次系统调用

perf stat -e syscalls:sys_enter_exit ls

只显示任务实行韶光,不显示性能计数器

perf stat -n ls > /dev/null record

记录一段韶光内系统/进程的性能韶光。

命令解析

-a, --all-cpus system-wide collection from all CPUs-b, --branch-any sample any taken branches-B, --no-buildid do not collect buildids in perf.data-c, --count <n> 事宜的采样周期-C, --cpu <cpu> 只采集指定CPU数据-d, --data 记录采样地址-D, --delay <n> 在测试程序开始后,在丈量前等等 n ms-F 指定采样频率-e, --event <event> 选择性能事宜-F, --freq <freq or 'max'> 指定频率-g 记录函数间的调用关系-G, --cgroup <name> 仅仅监视指定的cgroup name-I, --intr-regs[=<any register>] 每n毫秒打印计数增量(最小值:10ms).在某些情形下,开销可能很高,例如小于100毫秒的间隔。
-i, --no-inherit 禁止子任务继续父任务的性能计数器。
-j, --branch-filter <branch filter mask> 启用分支堆栈采样。
每个样本捕获一系列连续的采样分支。
-k, --clockid <clockid> 设置用于perf_event_type中各种韶光字段的时钟id记录。
请拜会clock_gettime()。
-m, --mmap-pages <pages[,pages]> mmap数据页面和赞助区域跟踪mmap页面的数量-N, --no-buildid-cache 不要更新buildid缓存-n, --no-samples 不要采样-o, --output <file> 指定输出文件,默认为perf.data-P, --period 采样周期-p, --pid <pid> 指定进程id-q, --quiet 不打印任何信息-R, --raw-samples 从所有打开的计数器网络原始样本记录-r, --realtime <n> 以 SCHED_FIFO 优先级实时网络数据-S, --snapshot[=<opts>] 快照模式-s, --stat 记录每个线程的事宜计数,利用perf report -T 查看可选值-t, --tid <tid> 在现有线程ID上记录事宜(逗号分隔列表)-T, --timestamp 记录采样韶光戳。
利用 perf report -D查看更详细信息-u, --uid <user> 指定用户id-W, --weight 启用加权采样
举例

记录实行ls时的性能数据

perf record ls -g

记录实行ls时的系统调用,可以知道哪些系统调用最频繁

perf record -e syscalls:sys_enter ls report

读取perf record天生的数据文件,并显示剖析数据。

-p<regex>:用指定正则表达式过滤调用函数-e <event>:指定性能事宜(可以是多个,用,分隔列表)-p <pid>:指定待剖析进程的 pid(可以是多个,用,分隔列表)-t <tid>:指定待剖析线程的 tid(可以是多个,用,分隔列表)-u <uid>:指定网络的用户数据,uid为名称或数字-a:从所有 CPU 网络系统数据-C <cpu-list>:只统计指定 CPU 列表的数据,如:0,1,3或1-2-r <RT priority>:perf 程序以SCHED_FIFO实时优先级RT priority运行这里填入的数值越大,进程优先级越高(即 nice 值越小)-c <count>: 事宜每发生 count 次采一次样-F <n>:每秒采样 n 次-o <output.data>:指定输出文件output.data,默认输出到perf.data-i:输入的数据文件-v:显示每个符号的地址-d <dos>:只显示指定dos的符号-S:只考虑指定符号-U:只显示已解析的符号-g[type,min,order]:显示调用关系,详细等同于perf top命令中的-g-c:只显示指定cpu采样信息-M:以指定汇编指令风格显示–source:以汇编和source的形式进行显示举例

记录实行ls时的性能数据

perf record ls -g

显示

perf report -i perf.data

overhead:cpu-clock占用百分比

command:当前实行的命令

shared object :依赖的共享库

symbol:当前占用比下对应的符号

[.]代表该调用属于用户态,若自己监控的进程为用户态进程,那么这些即紧张为用户态的cpu-clock占用的数值,[k]代表属于内核态的调用。

大概有的人会奇怪为什么自己完备是一个用户态的程序为什么还会统计到内核态的指标?

一是用户态程序运行时会受到内核态的影响,若内核态对用户态影响较大,统计内核态信息可以理解到是内核中的哪些行为导致对用户态产生影响;二则是有些用户态程序也须要依赖内核的某些操作,譬如I/O操作

annotate

perf annotate供应指令级别的record文件定位。
利用调试信息-g编译的文件能够显示汇编和本身源码信息。

但要把稳, annotate命令并不能够解析内核image中的符号,必须要通报未压缩的内核image给annotate才能正常的解析内核符号,比如:

perf annotate -k /tmp/vmlinux -d symbol命令解析

-i:输入文件名-d:只考虑这些DSO中的符号-f:逼迫读取-D:转储ASCII中的原始跟踪-k: vmlinux路径名-m:加载模块符号表.仅与-k和一起利用-l:打印匹配到的源代码行-P:显示完全路径名-M 指定反汇编程序样式-stdio:利用stdio接口-gtk:利用GTK接口举例

main.c内容如下:

#include <stdio.h>#include <time.h>void func_a() { unsigned int num = 1; int i; for (i = 0;i < 10000000; i++) { num = 2; num = 1; }}void func_b() { unsigned int num = 1; int i; for (i = 0;i < 10000000; i++) { num <<= 1; num = 1; }}int main() { func_a(); func_b(); return 0;}

编译命令:

gcc -g -O0 main.c #-g是debug信息,保留符号表等;-O0表示不进行优化处理

统计命令:

perf record -a -g ./a.out

perf report查当作果:

Samples: 73 of event 'cpu-clock', Event count (approx.): 18250000 Children Self Command Shared Object Symbol + 97.26% 0.00% a.out a.out [.] main + 97.26% 0.00% a.out libc-2.19.so [.] __libc_start_main + 49.32% 49.32% a.out a.out [.] func_a + 47.95% 47.95% a.out a.out [.] func_b + 1.37% 1.37% perf [kernel.kallsyms] [k] finish_task_switch + 1.37% 0.00% a.out ld-2.19.so [.] dl_main

perf annotate查当作果:

func_a /home/goodboy/tmp/a.out │ void func_a() { │ push %rbp │ mov %rsp,%rbp │ unsigned int num = 1; │ movl $0x1,-0x8(%rbp) │ int i; │ for (i = 0;i < 10000000; i++) { │ movl $0x0,-0x4(%rbp) │ ↓ jmp 22 │ num = 2; 11.11 │14:┌─→shll -0x8(%rbp) │ │ num = 1; │ │ movl $0x1,-0x8(%rbp) │ │#include <stdio.h> │ │#include <time.h> │ │void func_a() { │ │ unsigned int num = 1; │ │ int i; │ │ for (i = 0;i < 10000000; i++) { 5.56 │ │ addl $0x1,-0x4(%rbp) 33.33 │22:│ cmpl $0x98967f,-0x4(%rbp) 50.00 │ └──jle 14 │ num = 2; │ num = 1; │ } │ } │ pop %rbp │ ← retqtop

实时显示系统/进程的性能统计信息

命令解析

-e:指定性能事宜-a:显示在所有CPU上的性能统计信息-d:界面的刷新周期,默认为2s。
-C:显示在指定CPU上的性能统计信息-p:指定进程PID-t:指定线程TID-K:隐蔽内核统计信息-k:带符号表的内核映像所在的路径。
-U:隐蔽用户空间的统计信息-s:指定待解析的符号信息-g:得到函数的调用关系图。
‘‐G’ or‘‐‐call‐graph’ <output_type,min_percent,call_order>graph: 利用调用树,将每条调用路径进一步折叠。
这种显示办法更加直不雅观。
每条调用路径的采样率为绝对值。
也便是该条路径占全体采样域的比率。
fractal默认选项。
类似与 graph,但是每条路径前的采样率为相对值。
flat不折叠各条调用选项 call_order 用以设定调用图谱的显示顺序,该选项有 2个取值,分别是callee 与caller。
将该选项设为callee 时,perf按照被调用的顺序显示调用图谱,上层函数被下层函数所调用。
该选项被设为caller 时,按照调用顺序显示调用图谱,即上层函数调用了下层函数路径,也不显示每条调用路径的采样率
举例

显示分配高速缓存最多的函数

perf top -e kmem:kmem_cache_alloc

显示内核和模块中,花费最多CPU周期的函数

perf top -e cycles:k

第一列:符号引发的性能事宜的比例,默认指占用的cpu周期比例。

第二列:符号所在的DSO(Dynamic Shared Object),可以是运用程序、内核、动态链接库、模块。

第三列:DSO的类型。
[.]表示此符号属于用户态的ELF文件,包括可实行文件与动态链接库)。
[k]表述此符号属于内核或模块。

第四列:符号名。
有些符号不能解析为函数名,只能用地址表示。

bench

perf bench作为benchmark工具的通用框架,包含sched/mem/numa/futex等子系统,all可以指定所有。

perf bench可用于评估系统sched/mem等特定性能。

命令解析

-f, --format <default|simple> 选择输出格式,simple模式下只显示丈量韶光-r, --repeat <n> 指定重复运行的次数

子系统包括

sched:调度器和IPC机制。
包含messaging和pipe两个功能。

mem:内存存取性能。
包含memcpy和memset两个功能。

numa:NUMA架构的调度和内存处理性能。
包含mem功能。

futex:futex压力测试。
包含hash/wake/wake-parallel/requeue/lock-pi功能。

all:所有bench测试的凑集

举例

sched messaging评估进程调度和核间通信,sched message 是从经典的测试程序 hackbench 移植而来,用来衡量调度器的性能,overhead 以及可扩展性。

该 benchmark 启动 N 个 reader/sender 进程或线程对,通过 IPC(socket 或者 pipe) 进行并发的读写。
一样平常人们将 N 不断加大来衡量调度器的可扩展性。

sched message 的用法及用场和 hackbench 一样,可以通过修正参数进行不同目的测试:

-g, --group <n> Specify number of groups-l, --nr_loops <n> Specify the number of loops to run (default: 100)-p, --pipe Use pipe() instead of socketpair()-t, --thread Be multi thread instead of multi process

ubuntu# perf bench sched all# Running sched/messaging benchmark...# 20 sender and receiver processes per group# 10 groups == 400 processes run Total time: 0.077 [sec]# Running sched/pipe benchmark...# Executed 1000000 pipe operations between two processes Total time: 27.550 [sec] 27.550083 usecs/op 36297 ops/sec

利用pipe()和socketpair()对测试影响:

ubuntu# perf bench sched messaging# Running 'sched/messaging' benchmark:# 20 sender and receiver processes per group# 10 groups == 400 processes run Total time: 0.071 [sec]ubuntu# perf bench sched messaging -p# Running 'sched/messaging' benchmark:# 20 sender and receiver processes per group# 10 groups == 400 processes run Total time: 0.069 [sec]ubuntu#

可见socketpair()性能要明显低于pipe()。

利用perf剖析完全例子

下面我们举一个详细的例子来看下perf的利用方法。

//t1.c void longa() { int i,j; for(i = 0; i < 1000000; i++) j=i; //am I silly or crazy? I feel boring and desperate. } void foo2() { int i; for(i=0 ; i < 10; i++) longa(); } void foo1() { int i; for(i = 0; i< 100; i++) longa(); } int main(void) {while(1){ foo1(); foo2();} }统辖全局

先用 perf stat 查看下程序整体性能情形,该工具紧张是从全局上监控,可以看到程序导致性能瓶颈紧张是什么缘故原由。
perf stat通过概括精简的办法供应被调试程序运行的整体情形和汇总数据。

ubuntu# perf stat ./perf_test^C./perf_test: Interrupt Performance counter stats for './perf_test': 8,659.24 msec task-clock # 1.000 CPUs utilized 21 context-switches # 0.002 K/sec 0 cpu-migrations # 0.000 K/sec 43 page-faults # 0.005 K/sec <not supported> cycles <not supported> instructions <not supported> branches <not supported> branch-misses 8.660065455 seconds time elapsed 8.659661000 seconds user 0.000000000 seconds sys

task-clock :指程序运行期间占用了8,659.24 msec的任务时钟周期,该值高,解释程序的多数韶光花费在 CPU 打算上而非 IO。

context-switches :表示程序运行期间进行了21次高下文切换。
记录了程序运行过程中发生了多少次进程切换。

page-faults :是指程序发生了 43次缺页缺点。

通过perf stat得到了程序性能瓶颈类型后,已经知道哪个进程须要优化,若不知道则须要利用perf top进行进一步监控。

精准导航

下一步便是对该进程进行细粒度的剖析,剖析在长长的程序代码中究竟是哪几段代码、哪几个函数须要修正呢?

perf record -e cpu-clock -g ./perf_test

-g选项是见告perf record额外记录函数的调用关系,-e cpu-clock 指perf record监控的指标为cpu周期,程序运行完之后,perf record会天生一个名为perf.data的文件。

可视化剖析

前面通过perf record工具得到了某一进程的指标监控数据perf.data,下面就须要利用perf report工具查看该文件。

perf report -i perf.data

Self:是末了一列的符号(可以理解为函数)本身所占比例。

Children :是这个符号调用的其他符号(可以理解为子函数,包括直接和间接调用)占用的比例之和。

[.]:代表该调用属于用户态,若自己监控的进程为用户态进程,那么这些即紧张为用户态的cpu-clock占用的数值,[k]代表属于内核态的调用。

我们可以看到longa符号占用了perf_test程序的99%的CPU资源。

通过方向键和回车,可以看到函数的调用关系,同时以汇编代码的形式展示资源的花费情形。

addl $0x1,-0x8(%rbp)cmpl $0xf423f,-0x8(%rbp)

这两句汇编代码,先将0x8(%rbp)加一,然后和一个常数进行比较,霸占了63.5%的资源。

查看源代码可以创造做了一次1000000次的for循环。
接着以同样的方法, 可以创造foo1() 也是一个潜在的调优工具,为什么要调用 100 次那个无聊的 longa() 函数呢。

火焰图

on-cpu火焰图可以用于剖析cpu是被哪些线程、哪些函数占用的,可以方便的找到热点代码便于后续剖析优化。
下面我们先容下火焰图的天生和利用方法。

利用方法准备FlameGraph工具。

git clone https://github.com/brendangregg/FlameGraph.git用perf record采集CPU信息。

perf record -e cpu-clock -g ./perf_test

Ctrl+c结束实行后,在当前目录下会天生采样数据perf.data。

用perf script工具对perf.data进行解析。

perf script -i perf.data &> perf.unfold将perf.unfold中的符号进行折叠。

./stackcollapse-perf.pl perf.unfold &> perf.folded末了天生svg图。

./flamegraph.pl perf.folded > perf.svg

perf.svg 用浏览器就可以打开

火焰图解读

y 轴表示调用栈,每一层都是一个函数。
调用栈越深,火焰就越高,顶部便是正在实行的函数,下方都是它的父函数。

x 轴表示抽样数,如果一个函数在 x 轴霸占的宽度越宽,就表示它被抽到的次数多,即实行的韶光长。
把稳,x 轴不代表韶光,而是所有的调用栈合并后,按字母顺序排列的。

火焰图便是看顶层的哪个函数霸占的宽度最大。
只要有"平顶"(plateaus),就表示该函数可能存在性能问题。
比如图中的longa()函数正是问题所在点。

颜色没有分外含义,由于火焰图表示的是 CPU 的繁忙程度,以是一样平常选择暖色调。

互动

火焰图是SVG 图片,可以与用户互动。

火焰的每一层都会标注函数名,鼠标悬浮时会显示完全的函数名、抽样抽中的次数、霸占总抽样次数的百分比。
下面是一个例子。

在某一层点击,火焰图会水平放大,该层会霸占所有宽度,显示详细信息。
按下 Ctrl + F 会显示一个搜索框,用户可以输入关键词或正则表达式,所有符合条件的函数名会高亮显示。

其他

还有几个火焰图,就不先容了,可以去看brendang regg的网站,大略说一下:

off-cpu干系:

off-cpu flame graphs —— 与on-cpu互补,on-cpu只能看到运行情形,但如果某个要求运行慢,可能是被壅塞导致,那么就须要剖析壅塞点在代码的哪个位置,off-cpu便是画出每个壅塞点的壅塞韶光,用于剖析这个问题。
Wakeup flame graphs —— off-cpu的进一步,off-cpu画出了壅塞点,但不知道壅塞是被谁唤醒的,wakeup通过剖析唤醒壅塞点的线程栈,就可以知道是在哪里进行的唤醒,从而剖析唤醒慢的缘故原由。
Chain graphs —— off-cpu和wakeup火焰图画出了壅塞点、唤醒点,但两者之间的关系并没有,也便是不知道唤醒点是唤醒哪个壅塞点,chain graph便是办理这个问题

其他

Hot/Cold Flame Graphs —— 便是讲on-cpu与off-cpu结合,在一张图上显示,这样可以清晰的看到on和off各自的比例Differential Flame Graphs —— 比拟两个数据,画出来的图上显示变革情形,也便是相对之前的数据,每个部分占用是变高还是变低总结

利用perf+FlameGraph可以清晰的理解程序on-cpu运行韶光占比,可以高效的理解程序性能,这种方法对我们理解程序运行过程具有主要辅导浸染。
要长于利用工具帮助我们剖析繁芜问题。

本文参考

https://www.cnblogs.com/arnoldlu/p/6241297.html

https://www.cnblogs.com/lizhaolong/p/16437171.html

https://www.coonote.com/vim-note/perf-usage.html

https://developer.aliyun.com/article/131443

https://blog.csdn.net/qq_15437667/article/details/50724330

https://perf.wiki.kernel.org/index.php/Tutorial#Sample_analysis_with_perf_report

https://blog.csdn.net/ggsyxhhhh/article/details/104739296/

https://blog.csdn.net/runafterhit/article/details/107801860

标签:

相关文章