牛逼的性能分析工具 -perf

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

介绍

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的情况,帮助性能分析。

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