牛逼的性能分析工具 -perf

本贴最后更新于 956 天前,其中的信息可能已经水流花落

介绍

perf是linux性能分析中,比较常用的一款工具。它基于时间采集原理,以性能事件为基础,支持针对CPU处理器相关性能指标与操作系统相关性能指标的性能分析。常被用来查找、定位源码级性能问题。如,perf top,就常用来定位热点函数。

安装

如果系统中直接执行 perf --help不能执行,centos系统可以使用 yum install perf -y 进行安装,ubuntu系统可以使用 apt install linux-tools-common -y 安装

帮助

# perf -h 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解析perf record生成的perf.data文件,显示被注释的代码。     archive         Create archive with object files with build-ids found in perf.data file根据数据文件记录的build-id,将所有被采样到的elf文件打包,利用此压缩包,可以在任何机器上分析数据文件中记录的采样数据。     bench           General framework for benchmark suites。 perf中内存的benchmark,目前包括两套针对调度器和内存管理子系统的benchmark。     buildid-cache   Manage build-id cache.管理perf的build-id缓存,每个elf文件都有一个独一无二的build-id,build-id被perf用来关联性能数据和elf文件     buildid-list   List the buildids in a perf.data file 列出perf.data中记录的所有build-id。     c2c             Shared Data C2C/HITM Analyzer.   config         Get and set variables in a configuration file.获取配置文件中设置的变量   data           Data file related processing   diff           Read perf.data files and display the differential profile 对比两个perf.data文件差异,能够给出每个函数在热点分析上的具体差异。     evlist         List the event names in a perf.data file 列出perf.data文件中所有性能事件     ftrace         simple wrapper for kernel's ftrace functionality   inject         Filter to augment the events stream with additional information 该工具读取perf record工具记录的事件流,并将其定向到标准输出。在被分析代码中的任何一点,都可以向事件流中注入其它事件。     kallsyms       Searches running kernel for symbols   kmem           Tool to trace/measure kernel memory properties 针对内核内存(slab)子系统进行追踪测量的工具     kvm             Tool to trace/measure kvm guest os 用来追踪测试运行在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 收集采样信息,并将其记录在perf.data数据文件中。随后可通过其它工具对数据文件进行分析。     report         Read perf.data (created by perf record) and display the profile 读取perf record创建的数据文件,并给出热点分析结果。     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 执行某个命令,收集特定进程的性能概况,包括CPI、Cache丢失率等     test           Runs sanity tests.perf对当前软硬件平台进行健全性测试,可用此工具测试当前的软硬件平台是否能支持perf的所有功能。     timechart       Tool to visualize total system behavior during a workload 针对测试期间系统行为进行可视化的工具     top             System profiling tool. 类似于linux的top命令,对系统性能进行实时分析。   version         display the version of perf binary   probe           Define new dynamic tracepoints 用于定义动态检查点。   trace           strace inspired tool 关于syscall的工具。 See 'perf help COMMAND' for more information on a specific command.

对系统性能进行实时分析 perf top

# perf top -h Usage: perf top [<options>]    -a, --all-cpus       system-wide collection from all CPUs    -b, --branch-any     sample any taken branches    -c, --count <n>       event period to sample    -C, --cpu <cpu>       list of cpus to monitor    -d, --delay <n>       number of seconds to delay between refreshes    -D, --dump-symtab     dump the symbol table used for profiling    -E, --entries <n>     display this many functions    -e, --event <event>   event selector. use 'perf list' to list available events    -f, --count-filter <n>                         only display functions with more events than this    -F, --freq <freq or 'max'>                         profile at this frequency    -g                   enables call-graph recording and display    -i, --no-inherit     child tasks do not inherit counters    -j, --branch-filter <branch filter mask>                         branch stack filter modes    -K, --hide_kernel_symbols                         hide kernel symbols    -k, --vmlinux <file> vmlinux pathname    -M, --disassembler-style <disassembler style>                         Specify disassembler style (e.g. -M intel for intel syntax)    -m, --mmap-pages <pages>                         number of mmap data pages    -n, --show-nr-samples                         Show a column with the number of samples    -p, --pid <pid>       profile events on existing process id    -r, --realtime <n>   collect data with this RT SCHED_FIFO priority    -s, --sort <key[,key2...]>                          sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline, ... Please refer the man page for the complete list.    -t, --tid <tid>       profile events on existing thread id    -U, --hide_user_symbols                         hide user symbols    -u, --uid <user>     user to profile    -v, --verbose         be more verbose (show counter open errors, etc)    -w, --column-widths <width[,width...]>                         don't try to adjust column width, use these fixed values    -z, --zero           zero history across updates        --asm-raw         Display raw encoding of assembly instructions (default)        --call-graph <record_mode[,record_size],print_type,threshold[,print_limit],order,sort_key[,branch]>                         setup and enables call-graph (stack chain/backtrace):                               record_mode:   call graph recording mode (fp|dwarf|lbr)                               record_size:    if record_mode is 'dwarf', max size of stack recording (<bytes>)                                               default: 8192 (bytes)                               print_type:     call graph printing style (graph|flat|fractal|folded|none)                               threshold:     minimum call graph inclusion threshold (<percent>)                               print_limit:   maximum number of call graph entry (<number>)                               order:         call graph order (caller|callee)                               sort_key:       call graph sort key (function|address)                               branch:         include last branch info to call graph (branch)                               value:         call graph value (percent|period|count)                               Default: fp,graph,0.5,caller,function        --children       Accumulate callchains of children and show total overhead as well        --comms <comm[,comm...]>                         only consider symbols in these comms        --demangle-kernel                         Enable kernel symbol demangling        --dsos <dso[,dso...]>                         only consider symbols in these dsos        --fields <key[,keys...]>                         output field(s): overhead, period, sample plus all of sort keys        --force           don't complain, do it        --group           put the counters into a counter group        --hierarchy       Show entries in a hierarchy        --ignore-callees <regex>                         ignore callees of these functions in call graphs        --ignore-vmlinux don't load vmlinux even if found        --max-stack <n>   Set the maximum stack depth when parsing the callchain. Default: kernel.perf_event_max_stack or 127        --num-thread-synthesize <n>                         number of thread to run event synthesize        --objdump <path> objdump binary to use for disassembly and annotations        --overwrite       Use a backward ring buffer, default: no        --percent-limit <percent>                         Don't show entries under that percent        --percentage <relative|absolute>                         How to display percentage of filtered entries        --proc-map-timeout <n>                         per thread proc mmap processing timeout in ms        --raw-trace       Show raw trace event output (do not use print fmt or plugins)        --show-total-period                         Show a column with the sum of periods        --source         Interleave source code with assembly code (default)        --stdio           Use the stdio interface        --sym-annotate <symbol name>                         symbol to annotate        --symbols <symbol[,symbol...]>                         only consider these symbols        --tui             Use the TUI interface
[root@centos7 ~]# perf top -a Samples: 646K of event 'cpu-clock', 4000 Hz, Event count (approx.): 12702138322 lost: 0/0 drop: 0/0 Overhead Shared Object           Symbol  29.70% php-fpm                 [.] 0x00000000006250c2  

Samples: 采集cpu时钟事件的总样本数, 可以在命令中跟上 -e 事件 参数来指定跟踪的事件,perf list 命令,列出所有可跟踪的事件。

Event count: 事件总数量

Overhead: 符号引起的性能事件在总采样本中的百分比

Shared Object : 符号所在的DSO(Dynamic Shared Object),一般是应用程序、内核、动态连接库、模块

[.]表示此符号属于用户态的ELF文件,包括可执行文件与动态连接库;[k]表述此符号属于内核或模块。

Symbol: 符号名或函数名,未知时,用十六进制显示

perf top 常用的扩展参数有

参数 意思
-e 事件 指定要分析的事件
-p 进程id 仅分析目标进程及
-g 获取函数调用关系图
-k 路径 带符号表的内核映像所在的路径
-K 不显示属于内核或模块的符号
-U 不显示属于用户态程序的符号
-d 数字 界面刷新频率,默认2s
[root@centos7 ~]# perf list List 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] 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] block:block_bio_backmerge                         [Tracepoint event] block:block_bio_bounce                             [Tracepoint event] block:block_bio_complete                           [Tracepoint event] block:block_bio_frontmerge                         [Tracepoint event]

Software 是软件事件

Hardware\cache\Kernel PMU 都是硬件事件

Tracepoint是基于内核的ftrace

# 指定跟踪的事件 perf top -e block:block_rq_issue Samples: 11 of event 'block:block_rq_issue', 1 Hz, Event count (approx.): 1 lost: 0/0 drop: 1/8 Overhead 100.00%  14.29%  0,0 R 8 (4a 01 00 00 10 00 00 00 08 00) 0 + 0 [kworker/1:0]
# 跟踪某个进程的事件情况 [root@centos7 ~]# perf top -p 2087 Samples: 2K of event 'cpu-clock', 4000 Hz, Event count (approx.): 520562500 lost: 0/0 drop: 0/0 Overhead Shared Object     Symbol  29.87% php-fpm           [.] 0x00000000006250c2

具体跟踪某一个进程perf record -g p pid

[root@centos7 ~]# perf record -g -p 2181 # 收集一段较长时间后,ctrl+c 停止

执行命令之后,会在当前路径下生成一个 perf.data文件

分析perf.data文件

在有perf.data文件的路径下,执行 perf report

[root@centos7 ~]# perf report Samples: 142K of event 'cpu-clock', Event count (approx.): 35597750000, Thread: php-fpm Children     Self Command Shared Object       Symbol +   31.44%     0.00% php-fpm php-fpm             [.] 0x000056149fda70c2                                                                                   ◆ +   30.78%    30.78% php-fpm php-fpm             [.] 0x00000000006250c2  

看到里面的+号的行,可以回车,逐级往下定位

查看某个进程在一段时间内调用CPU情况 perf stat

perf stat -p 进程id # 执行一段时间后,ctrl+c停止 [root@centos7 ~]# perf stat -p 2399 ^C Performance counter stats for process id '2399':         93,774.02 msec task-clock                #   0.399 CPUs utilized            21,295     context-switches          #   0.227 K/sec               541     cpu-migrations            #   0.006 K/sec                 0     page-faults               #   0.000 K/sec   <not supported>     cycles   <not supported>     instructions   <not supported>     branches   <not supported>     branch-misses     235.027326843 seconds time elapsed
关键词 意思
msec task-clock\cpu-clock 任务真正占用处理器的时间,单位是ms
context-switches 程序在运行过程中,上下文切换次数
cpu-migrations 程序在运行过程中,处理器迁移次数,多核CPU时,
未来维护系统负载均衡,会出现从一个CPU切换到另外一个CPU的情况。
CPU迁移,一定会出现CPU上下文切换,
但CPU上下文切换,不一定会出现CPU迁移
page-faults 缺页异常次数。当应用程序请求的页面还没有创建、请求的页面不在内存中,
或者请求的页面虽然在内存中,
但物理地址和虚拟地址的映射关系还没有创建时,
都会触发一次缺页异常。
另外TLB不命中,页面访问权限不匹配等状况也会触发缺页异常
cycles 消耗的处理器的周期数
instructions 执行了多少条指令
branches 遇到的分支指令数
branch-misses 预测错误的分支指令数

通过这个,我们也能观察到进程使用CPU的情况,帮助性能分析。

回帖
请输入回帖内容 ...