系统级性能分析工具perf的介绍与使用

系统级性能分析工具perf的介绍与使用

2023年7月7日发(作者:)

系统级性能分析⼯具perf的介绍与使⽤测试环境:Ubuntu16.04 + Kernel:4.4.0-31

系统级性能优化通常包括两个阶段:性能剖析(performance profiling)和代码优化。性能剖析的⽬标是寻找性能瓶颈,查找引发性能问题的原因及热点代码。代码优化的⽬标是针对具体性能问题⽽优化代码或编译选项,以改善软件性能。

在性能剖析阶段,需要借助于现有的profiling⼯具,如perf等。在代码优化阶段往往需要借助开发者的经验,编写简洁⾼效的代码,甚⾄在汇编级别合理使⽤各种指令,合理安排各种指令的执⾏顺序。perf是⼀款Linux性能分析⼯具。Linux性能计数器是⼀个新的基于内核的⼦系统,它提供⼀个性能分析框架,⽐如硬件(CPU、PMU(Performance Monitoring Unit))功能和软件(软件计数器、tracepoint)功能。通过perf,应⽤程序可以利⽤PMU、tracepoint和内核中的计数器来进⾏性能统计。它不但可以分析制定应⽤程序的性能问题(per thread),也可以⽤来分析内核的性能问题,当然也可以同事分析应⽤程序和内核,从⽽全⾯理解应⽤程序中的性能瓶颈。使⽤perf,可以分析程序运⾏期间发⽣的硬件事件,⽐如instructions retired、processor clock cycles等;也可以分析软件时间,⽐如page fault和进程切换。

perf是⼀款综合性分析⼯具,⼤到系统全局性性能,再⼩到进程线程级别,甚⾄到函数及汇编级别。perf提供了⼗⼋般武器,可以拿⼤⼑⼤卸⼋块,也可以拿起⼿术⼑细致分析。1. 背景知识1.1 tracepointstracepoints是散落在内核源码中的⼀些hook,它们可以在特定的代码被执⾏到时触发,这⼀特定可以被各种trace/debug⼯具所使⽤。perf将tracepoint产⽣的时间记录下来,⽣成报告,通过分析这些报告,条有⼈缘便可以了解程序运⾏期间内核的各种细节,对性能症状做出准确的诊断。这些tracepint的对应的sysfs节点在/sys/kernel/debug/tracing/events⽬录下。1.2 硬件特性之cache内存读写是很快的,但是还是⽆法和处理器指令执⾏速度相⽐。为了从内存中读取指令和数据,处理器需要等待,⽤处理器时间来衡量,这种等待⾮常漫长。cache是⼀种SRAM,读写速度⾮常快,能和处理器相匹配。因此将常⽤的数据保存在cache中,处理器便⽆需等待,从⽽提⾼性能。cache的尺⼨⼀般都很⼩,充分利⽤cache是软件调优⾮常重要部分。

2. 主要关注点基于性能分析,可以进⾏算法优化(空间复杂度和时间复杂度权衡)、代码优化(提⾼执⾏速度、减少内存占⽤)。评估程序对硬件资源的使⽤情况,例如各级cache的访问次数、各级cache的丢失次数、流⽔线停顿周期、前端总线访问次数等。评估程序对操作系统资源的使⽤情况,系统调⽤次数、上下⽂切换次数、任务迁移次数。事件可以分为三种:1. Hardware Event由PMU部件产⽣,在特定的条件下探测性能事件是否发⽣以及发⽣的次数。⽐如cache命中。2. Software Event是内核产⽣的事件,分布在各个功能模块中,统计和操作系统相关性能事件。⽐如进程切换,tick数等。3. Tracepoint Event是内核中静态tracepoint所触发的事件,这些tracepoint⽤来判断程序运⾏期间内核的⾏为细节,⽐如slab分配器的分配次数等。

3. perf的使⽤perf --help之后可以看到perf的⼆级命令。序号命令171819annotatearchivebenchbuildid-cachediffevlistinjectkmemkvmlistlockmemrecordreportschedscriptstattest作⽤解析perf record⽣成的⽂件,显⽰被注释的代码。根据数据⽂件记录的build-id,将所有被采样到的elf⽂件打包。利⽤此压缩包,可以再任何机器上分析数据⽂件中记录的采样数据。perf中内置的benchmark,⽬前包括两套针对调度器和内存管理⼦系统的benchmark。管理perf的buildid缓存,每个elf⽂件都有⼀个独⼀⽆⼆的buildid。buildid被perf⽤来关联性能数据与elf⽂件。对⽐两个数据⽂件的差异。能够给出每个符号(函数)在热点分析上的具体差异。列出数据⽂件中所有性能事件。该⼯具读取perf record⼯具记录的事件流,并将其定向到标准输出。在被分析代码中的任何⼀点,都可以向事件流中注⼊其它事件。针对内核内存(slab)⼦系统进⾏追踪测量的⼯具⽤来追踪测试运⾏在KVM虚拟机上的Guest OS。列出当前系统⽀持的所有性能事件。包括硬件性能事件、软件性能事件以及检查点。分析内核中的锁信息,包括锁的争⽤情况,等待延迟等。内存存取情况收集采样信息,并将其记录在数据⽂件中。随后可通过其它⼯具对数据⽂件进⾏分析。读取perf record创建的数据⽂件,并给出热点分析结果。针对调度器⼦系统的分析⼯具。执⾏perl或python写的功能扩展脚本、⽣成脚本框架、读取数据⽂件中的数据信息等。执⾏某个命令,收集特定进程的性能概况,包括CPI、Cache丢失率等。perf对当前软硬件平台进⾏健全性测试,可⽤此⼯具测试当前的软硬件平台buildid-list列出数据⽂件中记录的所有buildid。是否能⽀持perf的所有功能。20212223timecharttoptraceprobe针对测试期间系统⾏为进⾏可视化的⼯具类似于linux的top命令,对系统性能进⾏实时分析。关于syscall的⼯具。⽤于定义动态检查点。全局性概况: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 report⽣成报告;perf diff对两个记录进⾏diff;perf evlist列出记录的性能事件;perf annotate显⽰函数代码;perf archive将相关符号打包,⽅便在其它机器进⾏分析;perf script将输出可读性⽂本;可视化⼯具perf timechartperf timechart record记录事件;perf timechart⽣成⽂档;

3.0 perf引⼊的overheadperf测试不可避免的会引⼊额外负荷,有三种形式:counting:内核提供计数总结,多是Hardware Event、Software Events、PMU计数等。相关命令perf stat。sampling:perf将事件数据缓存到⼀块buffer中,然后异步写⼊到⽂件中。使⽤perf report等⼯具进⾏离线分析。bpf:Kernel 4.4+新增功能,可以提供更多有效filter和输出总结。

counting引⼊的额外负荷最⼩;sampling在某些情况下会引⼊⾮常⼤的负荷;bpf可以有效缩减负荷。针对sampling,可以通过挂在建⽴在RAM上的⽂件系统来有效降低读写I/O引⼊的负荷。mkdir /tmpfsmount -t tmpfs tmpfs /tmpfs

3.1 perf listperf list不能完全显⽰所有⽀持的事件类型,需要sudo perf list。同时还可以显⽰特定模块⽀持的perf事件:hw/cache/pmu都是硬件相关的;tracepoint基于内核的ftrace;sw实际上是内核计数器。hw/hardware显⽰⽀持的硬件事件相关,如:al@al-System-Product-Name:~/perf$ sudo perf list hardwareList of pre-defined events (to be used in -e): branch-instructions OR branches [Hardware event] branch-misses [Hardware event] cache-misses [Hardware event] cache-references [Hardware event] cpu-cycles OR cycles [Hardware event] instructions [Hardware event] stalled-cycles-backend OR idle-cycles-backend [Hardware event] stalled-cycles-frontend OR idle-cycles-frontend [Hardware event]sw/software显⽰⽀持的软件事件列表:al@al-System-Product-Name:~/perf$ sudo perf list swList of pre-defined events (to be used in -e): 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]cache/hwcache显⽰硬件cache相关事件列表:al@al-System-Product-Name:~/perf$ sudo perf list cacheList of pre-defined events (to be used in -e): L1-dcache-load-misses [Hardware cache event] L1-dcache-loads [Hardware cache event] L1-dcache-prefetch-misses [Hardware cache event] L1-dcache-prefetches [Hardware cache event] L1-icache-load-misses [Hardware cache event] L1-icache-loads [Hardware cache event] L1-icache-prefetches [Hardware cache event] LLC-load-misses [Hardware cache event] LLC-loads [Hardware cache event] LLC-stores [Hardware cache event] branch-load-misses [Hardware cache event] branch-loads [Hardware cache event] dTLB-load-misses [Hardware cache event] dTLB-loads [Hardware cache event] iTLB-load-misses [Hardware cache event] iTLB-loads [Hardware cache event] node-load-misses [Hardware cache event] node-loads [Hardware cache event]pmu显⽰⽀持的PMU事件列表:al@al-System-Product-Name:~/perf$ sudo perf list pmuList of pre-defined events (to be used in -e): branch-instructions OR cpu/branch-instructions/ [Kernel PMU event] branch-misses OR cpu/branch-misses/ [Kernel PMU event] cache-misses OR cpu/cache-misses/ [Kernel PMU event] cache-references OR cpu/cache-references/ [Kernel PMU event] cpu-cycles OR cpu/cpu-cycles/ [Kernel PMU event] instructions OR cpu/instructions/ [Kernel PMU event] msr/aperf/ [Kernel PMU event] msr/mperf/ [Kernel PMU event] msr/tsc/ [Kernel PMU event] stalled-cycles-backend OR cpu/stalled-cycles-backend/ [Kernel PMU event] stalled-cycles-frontend OR cpu/stalled-cycles-frontend/ [Kernel PMU event]tracepoint显⽰⽀持的所有tracepoint列表,这个列表就⽐较庞⼤:al@al-System-Product-Name:~/perf$ sudo perf list tracepointList of pre-defined events (to be used in -e): alarmtimer:alarmtimer_cancel [Tracepoint event] alarmtimer:alarmtimer_fired [Tracepoint event] alarmtimer:alarmtimer_start [Tracepoint event] alarmtimer:alarmtimer_suspend [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]…

3.2 perf top默认情况下perf top是⽆法显⽰信息的,需要sudo perf top或者echo -1 > /proc/sys/kernel/perf_event_paranoid(在Ubuntu16.04,还需要echo 0 > /proc/sys/kernel/kptr_restrict)。即可以正常显⽰perf top如下:第⼀列:符号引发的性能事件的⽐例,指占⽤的cpu周期⽐例。第⼆列:符号所在的DSO(Dynamic Shared Object),可以是应⽤程序、内核、动态链接库、模块。第三列:DSO的类型。[.]表⽰此符号属于⽤户态的ELF⽂件,包括可执⾏⽂件与动态链接库;[k]表述此符号属于内核或模块。第四列:符号名。有些符号不能解析为函数名,只能⽤地址表⽰。关于perf top界⾯常⽤命令如下:h:显⽰帮助,即可显⽰详细的帮助信息。UP/DOWN/PGUP/PGDN/SPACE:上下和翻页。a:annotate current symbol,注解当前符号。能够给出汇编语⾔的注解,给出各条指令的采样率。d:过滤掉所有不属于此DSO的符号。⾮常⽅便查看同⼀类别的符号。P:将当前信息保存到.N中。

perf top常⽤选项有:-e :指明要分析的性能事件。-p :Profile events on existing Process ID (comma sperated list). 仅分析⽬标进程及其创建的线程。-k :Path to vmlinux. Required for annotation functionality. 带符号表的内核映像所在的路径。-K:不显⽰属于内核或模块的符号。-U:不显⽰属于⽤户态程序的符号。-d :界⾯的刷新周期,默认为2s,因为perf top默认每2s从mmap的内存区域读取⼀次性能数据。-g:得到函数的调⽤关系图。perf top --call-graph [fractal],路径概率为相对值,加起来为100%,调⽤顺序为从下往上。perf top --call-graph graph,路径概率为绝对值,加起来为该函数的热度。

3.3 perf statperf stat⽤于运⾏指令,并分析其统计结果。虽然perf top也可以指定pid,但是必须先启动应⽤才能查看信息。perf stat能完整统计应⽤整个⽣命周期的信息。命令格式为:perf stat [-e | --event=EVENT] [-a] perf stat [-e | --event=EVENT] [-a] — []下⾯简单看⼀下perf stat 的输出:al@al-System-Product-Name:~/perf$ sudo perf stat^C Performance counter stats for 'system wide': 40904.820871 cpu-clock (msec) # 5.000 CPUs utilized

18,132 context-switches # 0.443 K/sec

1,053 cpu-migrations # 0.026 K/sec

2,420 page-faults # 0.059 K/sec

3,958,376,712 cycles # 0.097 GHz (49.99%) 574,598,403 stalled-cycles-frontend # 14.52% frontend cycles idle (49.98%) 9,392,982,910 stalled-cycles-backend # 237.29% backend cycles idle (50.00%) 1,653,185,883 instructions # 0.42 insn per cycle

# 5.68 stalled cycles per insn (50.01%) 237,061,366 branches # 5.795 M/sec (50.02%) 18,333,168 branch-misses # 7.73% of all branches (50.00%) 8.181521203 seconds time elapsed输出解释如下:cpu-clock:任务真正占⽤的处理器时间,单位为ms。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是预测错误的分⽀指令数。

其他常⽤参数 -a, --all-cpus 显⽰所有CPU上的统计信息 -C, --cpu 显⽰指定CPU的统计信息 -c, --scale scale/normalize counters -D, --delay ms to wait before starting measurement after program start -d, --detailed detailed run - start a lot of events -e, --event event selector. use 'perf list' to list available events -G, --cgroup monitor event in cgroup name only -g, --group put the counters into a counter group -I, --interval-print 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 输出统计信息到⽂件 -p, --pid stat events on existing process id -r, --repeat repeat command and print average + stddev (max: 100, forever: 0) -S, --sync call sync() before starting a run -t, --tid stat events on existing ⽰例前⾯统计程序的⽰例,下⾯看⼀下统计CPU信息的⽰例:执⾏sudo perf stat -C 0,统计CPU 0的信息。想要停⽌后,按下Ctrl+C终⽌。可以看到统计项⼀样,只是统计对象变了。al@al-System-Product-Name:~/perf$ sudo perf stat -C 0^C Performance counter stats for 'CPU(s) 0': 2517.107315 cpu-clock (msec) # 1.000 CPUs utilized

2,941 context-switches # 0.001 M/sec

109 cpu-migrations # 0.043 K/sec

38 page-faults # 0.015 K/sec

644,094,340 cycles # 0.256 GHz (49.94%) 70,425,076 stalled-cycles-frontend # 10.93% frontend cycles idle (49.94%) 965,270,543 stalled-cycles-backend # 149.86% backend cycles idle (49.94%) 623,284,864 instructions # 0.97 insn per cycle

# 1.55 stalled cycles per insn (50.06%) 65,658,190 branches # 26.085 M/sec (50.06%) 3,276,104 branch-misses # 4.99% of all branches (50.06%) 2.516996126 seconds time elapsed如果需要统计更多的项,需要使⽤-e,如:perf stat -e task-clock,context-switches,cpu-migrations,page-faults,cycles,stalled-cycles-frontend,stalled-cycles-backend,instructions,branches,branch-misses,L1-dcache-loads,L1-dcache-load-misses,LLC-loads,LLC-load-misses,dTLB-loads,dTLB-load-misses ls结果如下,关注的特殊项也纳⼊统计。al@al-System-Product-Name:~/perf$ sudo perf stat -e task-clock,context-switches,cpu-migrations,page-faults,cycles,stalled-cycles-frontend,stalled-cycles-backend,instructions,branches,branch-misses,L1-dcache-loads,L1-dcache-load-misses,LLC-loads,LLC-load-misses,dTLB-loads,dTLB-load-misses lsPerformance counter stats for 'ls': 2.319422 task-clock (msec) # 0.719 CPUs utilized

0 context-switches # 0.000 K/sec

0 cpu-migrations # 0.000 K/sec

89 page-faults # 0.038 M/sec

2,142,386 cycles # 0.924 GHz

659,800 stalled-cycles-frontend # 30.80% frontend cycles idle

725,343 stalled-cycles-backend # 33.86% backend cycles idle

1,344,518 instructions # 0.63 insn per cycle

# 0.54 stalled cycles per insn branches

branch-misses

L1-dcache-loads

L1-dcache-load-misses

LLC-loads

LLC-load-misses

dTLB-loads

dTLB-load-misses

0.003227507 seconds time elapsed

3.4 perf benchperf bench作为benchmark⼯具的通⽤框架,包含sched/mem/numa/futex等⼦系统,all可以指定所有。perf bench可⽤于评估系统sched/mem等特定性能。perf bench sched:调度器和IPC机制。包含messaging和pipe两个功能。perf bench mem:内存存取性能。包含memcpy和memset两个功能。perf bench numa:NUMA架构的调度和内存处理性能。包含mem功能。perf bench futex:futex压⼒测试。包含hash/wake/wake-parallel/requeue/lock-pi功能。perf bench all:所有bench测试的集合

3.4.1 perf bench sched all测试messaging和pipi两部分性能。3.4.1.1 sched messaging评估进程调度和核间通信sched message 是从经典的测试程序 hackbench 移植⽽来,⽤来衡量调度器的性能,overhead 以及可扩展性。该 benchmark 启动 N 个 reader/sender 进程或线程对,通过 IPC(socket 或者 pipe) 进⾏并发的读写。⼀般⼈们将 N 不断加⼤来衡量调度器的可扩展性。sched message 的⽤法及⽤途和 hackbench ⼀样,可以通过修改参数进⾏不同⽬的测试:-g, --group Specify number of groups-l, --nr_loops 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测试结果:al@al-System-Product-Name:~/perf$ perf bench sched all# Running sched/# 20 sender and receiver processes per group# 10 groups == 400 processes run Total time: 0.173 [sec]# Running sched/# Executed 1000000 pipe operations between two processes Total time: 12.233 [sec] 12.233170 usecs/op 81744 ops/sec使⽤pipe()和socketpair()对测试影响:1. perf bench sched messaging# Running 'sched/messaging' benchmark:# 20 sender and receiver processes per group# 10 groups == 400 processes run Total time: 0.176 [sec]2. perf bench sched messaging -p# Running 'sched/messaging' benchmark:# 20 sender and receiver processes per group# 10 groups == 400 processes run Total time: 0.093 [sec]可见socketpair()性能要明显低于pipe()。

3.4.1.2 sched pipe评估pipe性能sched pipe 从 Ingo Molnar 的 pipe-test-1m.c 移植⽽来。当初 Ingo 的原始程序是为了测试不同的调度器的性能和公平性的。其⼯作原理很简单,两个进程互相通过 pipe 拼命地发 1000000 个整数,进程 A 发给 B,同时 B 发给 A。因为 A 和 B 互相依赖,因此假如调度器不公平,对 A ⽐ B 好,那么 A和 B 整体所需要的时间就会更长。al@al-System-Product-Name:~/perf$ perf bench sched pipe# Running 'sched/pipe' benchmark:# Executed 1000000 pipe operations between two processes Total time: 12.240 [sec] 12.240411 usecs/op 81696 ops/sec

3.4.2 perf bench mem all该测试衡量 不同版本的memcpy/memset/ 函数处理⼀个 1M 数据的所花费的时间,转换成吞吐率。al@al-System-Product-Name:~/perf$ perf bench mem all# Running mem/# function 'default' (Default memcpy() provided by glibc)# Copying 1MB bytes ... 1.236155

3.4.3 perf bench futexFutex是⼀种⽤户态和内核态混合机制,所以需要两个部分合作完成,linux上提供了sys_futex系统调⽤,对进程竞争情况下的同步处理提供⽀持。所有的futex同步操作都应该从⽤户空间开始,⾸先创建⼀个futex同步变量,也就是位于共享内存的⼀个整型计数器。当进程尝试持有锁或者要进⼊互斥区的时候,对futex执⾏"down"操作,即原⼦性的给futex同步变量减1。如果同步变量变为0,则没有竞争发⽣, 进程照常执⾏。如果同步变量是个负数,则意味着有竞争发⽣,需要调⽤futex系统调⽤的futex_wait操作休眠当前进程。当进程释放锁或 者要离开互斥区的时候,对futex进⾏"up"操作,即原⼦性的给futex同步变量加1。如果同步变量由0变成1,则没有竞争发⽣,进程照常执⾏。如果加之前同步变量是负数,则意味着有竞争发⽣,需要调⽤futex系统调⽤的futex_wake操作唤醒⼀个或者多个等待进程。al@al-System-Product-Name:~/perf$ perf bench futex all# Running futex/Run summary [PID 3806]: 5 threads, each operating on 1024 [private] futexes for 10 secs.[thread 0] futexes: 0x4003d20 ... 0x4004d1c [ 4635648 ops/sec ][thread 1] futexes: 0x4004d30 ... 0x4005d2c [ 4611072 ops/sec ][thread 2] futexes: 0x4005e70 ... 0x4006e6c [ 4254515 ops/sec ][thread 3] futexes: 0x4006fb0 ... 0x4007fac [ 4559360 ops/sec ][thread 4] futexes: 0x40080f0 ... 0x40090ec [ 4636262 ops/sec ]Averaged 4539371 operations/sec (+- 1.60%), total secs = 10# Running futex/Run summary [PID 3806]: blocking on 5 threads (at [private] futex 0x96b52c), waking up 1 at a time.[Run 1]: Wokeup 5 of 5 threads in 0.0270 ms[Run 2]: Wokeup 5 of 5 threads in 0.

3.4 perf record运⾏⼀个命令,并将其数据保存到中。随后,可以使⽤perf report进⾏分析。perf record和perf report可以更精确的分析⼀个应⽤,perf record可以精确到函数级别。并且在函数⾥⾯混合显⽰汇编语⾔和代码。创建⼀个fork.c⽂件⽤于测试: #include void test_little(void){ int i,j; for(i = 0; i < 30000000; i++)

j=i;

}void test_mdedium(void){ int i,j; for(i = 0; i < 60000000; i++)

j=i;

}void test_high(void){ int i,j; for(i = 0; i < 90000000; i++)

j=i;

}void test_hi(void){ int i,j; for(i = 0; i < 120000000; i++)

j=i;

}int main(void){ int i, pid, result; for(i = 0; i<2; i++) { result = fork(); if(result>0) printf("i=%d parent parent=%d current=%d child=%dn", i, getppid(), getpid(), result); else printf("i=%d child parent=%d current=%dn", i, getppid(), getpid()); if(i==0) { test_little(); sleep(1); } else { test_mdedium(); sleep(1); } } pid = wait(NULL); test_high(); printf("pid=%d wait=%dn", getpid(), pid); sleep(1); pid = wait(NULL); test_hi(); printf("pid=%d wait=%dn", getpid(), pid); return 0;}

编译fork.c⽂件gcc fork.c -o fork-g -O0,同时可以使⽤此⽅法分析是否选择编译优化产⽣的结果。-g是只能callgraph功能,-O0是关闭优化。常⽤选项-e record指定PMU事件 --filter event事件过滤器-a 录取所有CPU的事件-p 录取指定pid进程的事件-o 指定录取保存数据的⽂件名-g 使能函数调⽤图功能-C 录取指定CPU的事件

sudo perf record -a -g ./fork:会在当前⽬录⽣成⽂件。sudo perf report --call-graph none结果如下,后⾯结合perf timechart分析.

上图看上去⽐较乱,如果想只看fork产⽣的信息:sudo perf report --call-graph none -c fork可以看出只显⽰了fork程序的相关符号及其占⽤率。

3.5 perf report解析perf record产⽣的数据,并给出分析结果。常⽤参数:-i 导⼊的数据⽂件名称,如果没有则默认为-g ⽣成函数调⽤关系图,此时内核要打开CONFIG_KALLSYMS;⽤户空间库或者执⾏⽂件需要带符号信息(not stripped),编译选项需要加上-g。--sort 从更⾼层⾯显⽰分类统计信息,⽐如: pid, comm, dso, symbol, parent, cpu,socket, srcline, weight, local_weight.执⾏sudo perf report -i ,可以看出main函数所占百分⽐,以及funcA和funcB分别所占百分⽐。在funcB执⾏过程中,还产⽣了apic timer,占⽤了⼀部分cpu资源。除此之外,占⽐基本上是1:10。funcA和funcB的占⽐,基本符合预期。那么进⼊longa,分析⼀下热点。在C和汇编混合显⽰界⾯,可以看出for循环占⽤了69.92%,j=i赋值占⽤了30.08%。根据之上描述,可以看出top适合监控整个系统的性能,stat⽐较适合单个程序的性能分析,record/report更适合对程序进⾏更细粒度的分析。

注意点:在使⽤perf report -g的时候,可能会提⽰Failed to open /lib/, continuing without symbols。这时候通过file xxx查看,如果提⽰xxxx stripped表⽰此⽂件不包含符号信息,需要xxxx not stripped⽂件。

3.6 perf timechartperf timechart是将之前的各种统计信息图形化的⼀个⼯具。perf timechart record

perf timechart record可以指定特定类型的事件:-P:记录power相关事件-T:记录任务相关事件-I:记录io相关事件-g:记录函数调⽤关系perf timechart⽤于将perf timechart record录取的转换成。-w调整输出的svg⽂件长度,可以查看更多细节。-p可以指定只查看某些进程输出,使⽤⽅式:sudo perf timechart -p test1 -p thermald-o 指定输出⽂件名-i 指定待解析的⽂件名-w 输出SVG⽂件宽度-P 只显⽰power相关事件图标-T , --tasks-only 显⽰task信息,不显⽰处理器信息-p 显⽰指定进程名称或者PID显⽰--symfs= 指定系统符号表路径-t, --topology 根据拓扑结构对CPU进⾏分类--highlight= 对运⾏超过特定时间的task⾼亮

当线程太多影响svg解析速度的时候,可以通过-p指定特定线程进⾏分析。如果需要⼏个线程,每个线程采⽤-p xxx。sudo perf timechart record -T ./fork && sudo perf timechart –p fork结果如下,可以看到相关task的名称,开始时间/结束时间,每个时间点的状态(Running/Idle/Deeper Idle/Deepest Idle/Sleeping/Waiting for Cpu /Blocked on IO)。3.6.1 结合perf timechart和perf report分析函数占⽐由perf report可知test_little、test_medium、test_high、test_hi四个函数占⽐分别为3.84%、12.01%、22.99%、30.43%。有代码可知如果以test_little为1单位,那么test_medium就为2单位,test_high为3单位,test_hi为4单位。四个函数执⾏次数分别为2、4、4、4,所以四个函数每个单位对应CPU占⽐为:test_little - 3.84%/2=1.9%test_medium - 12.01%/4/2=1.5%test_high - 22.99/4/3=1.9%test_hi - 30.43%/4/4=1.9%基本上符合预期。

记录IO事件,可以看到按应⽤分类的,Disk/Network/Sync/Poll/Error信息。以及每个应⽤数据吞吐量。sudo perf timechart record -I && sudo perf timechart -w 1800。

记录Power状态事件,可以看到不同之处在于Idle之类的状态⾥⾯还有细分C/C2更详细的显⽰Power状态。sudo perf timechart record -I && sudo perf timechart -w 1800

3.7 perf script⽤于读取perf record保存的裸trace数据。使⽤⽅法: perf script [] perf script [] record

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信