首页 > 系统相关 >Linux动态追踪——perf

Linux动态追踪——perf

时间:2024-03-13 10:58:05浏览次数:27  
标签:fork do perf centos probe Linux root 追踪

目录

摘要 

跟踪系统调用

跟踪事件

跟踪函数

跟踪内核函数

 跟踪用户函数

性能分析

perf stat 与 perf top 

火焰图

​编辑 总结


摘要 

     ftrace 和 perf 都是 Linux 提供的动态追踪功能,两者有一定相似性,却又有不同的侧重点。ftrace 更侧重于事件跟踪和内核行为的实时分析,perf 更侧重于性能分析和事件统计。

跟踪系统调用

        一般对于用户进程的系统调用跟踪,常用 strace :

[root@centos ~]# strace -p 1545
strace: Process 1545 attached
select(0, NULL, NULL, NULL, {tv_sec=0, tv_usec=636974}) = 0 (Timeout)
wait4(1552, 0x7ffccc4863c4, WNOHANG, NULL) = 0
wait4(1553, 0x7ffccc4863c4, WNOHANG, NULL) = 0

        strace 用起来简单,但其实有不可忽略的性能问题。究其原因,乃是因为 strace 基于 ptrace() 系统调用实现,在事件多的场景下,存在频繁的用户态、内核态之间的切换,因此需尽量避免在线上环境使用。

        perf 也提供了 trace 功能,不同的是,perf 基于内核事件实现,性能较 strace 要优越许多。

比如我们可以通过这样的命令跟踪指定的进程:

[root@centos ~]# perf trace -p 1545
         ? (         ):  ... [continued]: select()) = 0 Timeout
     0.029 ( 0.004 ms): wait4(upid: 1552 (barad_agent), stat_addr: 0x7ffccc4863c4, options: NOHANG
     0.039 ( 0.003 ms): wait4(upid: 1553 (barad_agent), stat_addr: 0x7ffccc4863c4, options: NOHANG
     0.049 (5000.708 ms): select(tvp: 0x7ffccc486860                                            ) = 0 Timeout

        可惜的是,由于 perf 基于内核的跟踪点信息实现,这些信息不一定完整,所以 perf 的输出不一定有参数和返回值信息。

跟踪事件

        同 ftrace 一样,perf 也支持事件跟踪,perf list 描述了其预定义的跟踪事件:

[root@centos ~]# perf list | grep net
  net:napi_gro_frags_entry                           [Tracepoint event]
  net:napi_gro_receive_entry                         [Tracepoint event]
  net:net_dev_queue                                  [Tracepoint event]
  net:net_dev_xmit                                   [Tracepoint event]
  net:netif_receive_skb                              [Tracepoint event]
  net:netif_receive_skb_entry                        [Tracepoint event]
  net:netif_rx                                       [Tracepoint event]
  net:netif_rx_entry                                 [Tracepoint event]
  net:netif_rx_ni_entry                              [Tracepoint event]

        支持的事件种类也是比较多的,可以通过 -e 指定感兴趣的事件进行跟踪。这里我们还是以 netif_receive_skb 为例测试一下:

[root@centos ~]# perf record -e net:netif_receive_skb
^C[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.149 MB perf.data (10 samples) ]

[root@centos ~]# perf script
         swapper     0 [001] 14224.192066: net:netif_receive_skb: dev=eth0 skbaddr=0xffff96c9b9a10800 len=28
         swapper     0 [001] 14224.780290: net:netif_receive_skb: dev=eth0 skbaddr=0xffff96c9b9a10800 len=132
         swapper     0 [001] 14224.784794: net:netif_receive_skb: dev=eth0 skbaddr=0xffff96c9b9a10500 len=52
         swapper     0 [000] 14225.050872: net:netif_receive_skb: dev=eth0 skbaddr=0xffff96c9b9bafd00 len=52

跟踪函数

        当然了,如果这些预定义的事件并不满足我们的需求,perf 也支持我们自己指定函数名,这就要用的 perf probe 工具了。  

跟踪内核函数

        让我们来用 perf probe 跟踪一下 do_fork() 这个内核函数,首先通过 --add 选项添加要跟踪的函数名:

[root@centos ~]# perf probe --add do_fork
Added new event:
  probe:do_fork        (on do_fork)

You can now use it in all perf tools, such as:

        perf record -e probe:do_fork -aR sleep 1

        然后按照提示执行 perf record 就好了:

[root@centos ~]# perf record -e probe:do_fork -aR sleep 1
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.163 MB perf.data (16 samples) ]
[root@centos ~]# 
[root@centos ~]# perf script
           crond  1230 [001] 16150.475442: probe:do_fork: (ffffffff8b29e700)
           crond  3271 [001] 16150.480182: probe:do_fork: (ffffffff8b29e700)
           flock  3272 [000] 16150.481877: probe:do_fork: (ffffffff8b29e700)
              sh  3273 [001] 16150.482651: probe:do_fork: (ffffffff8b29e700)
        start.sh  3274 [000] 16150.483937: probe:do_fork: (ffffffff8b29e700)
        start.sh  3274 [001] 16150.484779: probe:do_fork: (ffffffff8b29e700)
        start.sh  3276 [000] 16150.484940: probe:do_fork: (ffffffff8b29e700)
        start.sh  3276 [000] 16150.485024: probe:do_fork: (ffffffff8b29e700)
[root@centos ~]# perf probe --del do_for

         最后也还是要记得删掉 probe 的跟踪点。上面的输出就是 perf 在 1s 内采样输出的结果了。实际中,我们可能还需要指定 do_fork 的参数具体传了什么。

[root@centos ~]# perf probe -V do_fork
Available variables at do_fork
        @<do_fork+0>
                int*    child_tidptr
                int*    parent_tidptr
                long unsigned int       clone_flags
                long unsigned int       stack_size
                long unsigned int       stack_start

        如果提示找不到符号,那可能是没有安装 kernel-debuginfo 包,可以下载对应版本的 rpm 来手动安装:

wget http://debuginfo.centos.org/7/x86_64/kernel-debuginfo-common-x86_64-$(uname -r).rpm
wget http://debuginfo.centos.org/7/x86_64/kernel-debuginfo-$(uname -r).rpm

rpm -ivh kernel-debuginfo-common-x86_64-$(uname -r).rpm
rpm -ivh kernel-debuginfo-$(uname -r).rpm

         知道了参数之后,就可以用如下的方法跟踪函数的参数啦:

[root@centos ~]# perf probe --add 'do_fork child_tidptr clone_flags'
Added new event:
  probe:do_fork        (on do_fork with child_tidptr clone_flags)

You can now use it in all perf tools, such as:

        perf record -e probe:do_fork -aR sleep 1

[root@centos ~]# perf record -e probe:do_fork -aR sleep 3
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.171 MB perf.data (26 samples) ]
[root@centos ~]# 
[root@centos ~]# perf script
     barad_agent  1566 [001] 19545.036400: probe:do_fork: (ffffffff8b29e700) child_tidptr=0x7fb2cc9939d0 clone_flags=0x3d0
     barad_agent 16816 [001] 19545.036916: probe:do_fork: (ffffffff8b29e700) child_tidptr=0x7fb2cc9939d0 clone_flags=0x120
     barad_agent  1566 [000] 19545.037944: probe:do_fork: (ffffffff8b29e700) child_tidptr=0x7fb2bf1ca9d0 clone_flags=0x3d0
# 记得删掉跟踪点
[root@centos ~]# perf probe --del 'do_fork'
Removed event: probe:do_fork

跟踪用户函数

        同样的,perf 也可以跟踪用户空间的函数调用。bash 作为命令行输入的窗口,会调用 readline 方法从标准 io 读取用户的输入,并返回一个字符串,我们可以通过如下的命令对其进行跟踪:

[root@centos ~]# perf probe -x /bin/bash 'readline%return +0($retval):string'
Added new event:
  probe_bash:readline__return (on readline%return in /usr/bin/bash with +0($retval):string)

You can now use it in all perf tools, such as:

        perf record -e probe_bash:readline__return -aR sleep 1

[root@centos ~]# perf record -e probe_bash:readline__return -aR sleep 5
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.173 MB perf.data (1 samples) ]
[root@centos ~]# 
[root@centos ~]# perf script
[root@centos ~]# perf record -e probe_bash:readline__return -aR sleep 3
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.184 MB perf.data ]
[root@centos ~]# 
[root@centos ~]# perf script
            bash  3289 [000] 19913.376245: probe_bash:readline__return: (48aea0 <- 41e75a) arg1="pwd"
# 删除跟踪点
[root@centos ~]# perf probe --del probe_bash:readline__return
Removed event: probe_bash:readline__return

       如果不清楚参数,但是有带符号表的二进制文件的话,也可以通过以下的命令查询函数名及参数:

# 通过 -x 指定二进制路径,--funcs 查询方法名
[root@centos ~]# perf probe -x ./a.out --funcs
completed.6355
data_start
deregister_tm_clones
frame_dummy
fun
main
printf@plt
register_tm_clones
# 查询 fun 方法的参数
[root@centos ~]# perf probe -x ./a.out -V fun
Available variables at fun
        @<fun+0>
                int     a

性能分析

perf stat 与 perf top 

       除了跟踪,perf最常用的就是性能分析了。如通过 perf stat 统计消耗时钟周期及缺页次数:

[root@centos ~]# perf stat -e cpu-clock,page-faults
^C
 Performance counter stats for 'system wide':

          6,053.73 msec cpu-clock                 #    2.000 CPUs utilized          
             2,345      page-faults               #    0.387 K/sec                  

       3.026891428 seconds time elapsed

        通过 perf top -g 对热点函数及调用栈进行采样,光标移动到对应的行上按下 Enter 就可以展开调用栈:

Samples: 3K of event 'cpu-clock', 4000 Hz, Event count (approx.): 409744295 lost: 0/0 drop: 0/0
  Children      Self  Shared Object         Symbol
-   14.10%     0.59%  [kernel]              [k] __do_softirq                                                             ◆
   + 2.22% __do_softirq                                                                                                  ▒
+   10.27%     0.06%  [kernel]              [k] arch_cpu_idle                                                            ▒
-    9.42%     0.05%  [kernel]              [k] system_call_fastpath                                                     ▒
+    8.79%     8.79%  [kernel]              [k] _raw_spin_unlock_irqrestore                                         

        perf top 帮助我们清晰的看到热点函数的,包括占用的 cpu 时间比以及所属进程或是动态库。

火焰图

        有时候光看这些符号对个函数整体占用的分布并没有直观的感受,这时候火焰图就派上了用场。

        生成火焰图需要依赖一个开源的脚本工具,从这里下载即可:

https://github.com/brendangregg/FlameGraph

        脚本准备完毕可以开始执行下面的命令生成火焰图了,具体用法在对应脚本中也有详细的注释说明: 

# 统计热点函数及调用栈信息
[root@centos ~]# perf record -F 99 -a -g -- sleep 5
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.282 MB perf.data (990 samples) ]
# 调用脚本生成火焰图
[root@centos ~]# perf script | ./FlameGraph-master/stackcollapse-perf.pl > out.tmp && ./FlameGraph-master/flamegraph.pl out.tmp > out.svg

        生成的火焰图效果如下,其横轴为样本的数量,可以理解为耗时的近似值,纵轴表示调用栈的深度,图的底部即时调用栈的最底层:

 总结

        总结来说,perf 常用的功能就是 trace 跟踪函数、事件,top、stat、record 统计分析性能。配合第三方脚本生成火焰图提供可视化的界面。perf 提供的功能还不止于此,不过知道这些常用的方法也能帮助我们排查问题及性能优化了。

标签:fork,do,perf,centos,probe,Linux,root,追踪
From: https://blog.csdn.net/qq_33724710/article/details/136635083

相关文章

  • linux Shell 命令行-07-func 函数
    拓展阅读linuxShell命令行-00-intro入门介绍linuxShell命令行-02-var变量linuxShell命令行-03-array数组linuxShell命令行-04-operator操作符linuxShell命令行-05-test验证是否符合条件linuxShell命令行-06-flowcontrol流程控制linuxShell命令行-07-f......
  • linux 程序状态查询脚本
    linux程序状态查询脚本#!/bin/bashsource/etc/profileDOCKERCOMPOSE=/usr/local/bin/docker-composeSHELL_FOLDER=$(cd"$(dirname"$0")";pwd)action=${1-}#workdir=$PWD#cd$workdir#docker-composepsfunctionGetApollo(){echo""......
  • linux文件管理与用户管理
    linux文件管理与用户管理1、查看文件内容1、1回顾之前的命令cat命令tac命令head命令tail命令扩展:tail-f动态查看一个文件的内容1、2more命令分屏显示文件基本语法:#more文件名称特别注意:more命令在加载文件时并不是一点一点进行加载,而是打开文件就已经把文件内容......
  • linux文件管理(补充)
    linux文件管理vim编辑器vi概述vi编辑器他是linux和unix系统上最基本的文本编辑器,类似于windows系统下的记事本编辑器vim编辑器vim是vi的加强版,比vi更容易使用。vi的命令几乎全部都可以在vim上使用命令模式使用vim编辑器时,默认处于命令模式。在该模式下可以移动光标位置,可......
  • 如何在 Linux 中禁用 IPv6?
    IPv6(InternetProtocolversion6)是互联网上的下一代网络协议,它的部署旨在解决IPv4地址枯竭的问题,并提供更多的地址空间以支持未来的互联网增长。然而,在某些情况下,禁用IPv6可能是必要的,例如在特定网络环境下IPv6不可用或不安全时。本文将介绍在Linux系统中如何禁用IPv6的方......
  • Linux内存监控的12种方法全面掌握系统资源使用情况
    监控系统的内存使用情况是系统管理和性能优化的关键部分之一。在Linux环境下,有多种方法来实现对内存的监控和管理。本文将介绍12种常用的方法,涵盖了从基本的命令行工具到更高级的监控工具的使用,帮助您全面掌握系统的资源使用情况。1.free命令free 命令用于显示系统内......
  • 【linux】HTTP资源概念;URL,URI,MIME,静态,动态,伪静态核心名词知识全面讲解
    鱼弦:公众号:红尘灯塔,CSDN内容合伙人、CSDN新星导师、51CTO(Top红人+专家博主) 、github开源爱好者(go-zero源码二次开发、游戏后端架构https://github.com/Peakchen)HTTP资源概念:HTTP资源是通过HTTP协议访问的可识别和可获取的信息。它可以是文本、图像、视频、音频、网页......
  • 在Linux中,访问一个站点5xx了,如何定位问题?
    当访问一个托管在Linux服务器上的站点时,如果收到5xx系列的HTTP状态码(如500InternalServerError、502BadGateway、503ServiceUnavailable等),这意味着服务器在处理请求时遇到了问题。定位这类问题通常需要遵循以下步骤:查看服务器错误日志对于Web服务器,如Apache或Nginx,首......
  • 在Linux中,ansible可以解决哪些问题?
    Ansible是一款强大的IT自动化工具,主要用于解决运维过程中面临的诸多挑战,特别适合批量管理和配置大量服务器。以下是Ansible可以帮助解决的一些典型问题:配置管理和标准化:Ansible能够通过Playbook(剧本)的形式编写和组织配置任务,确保在多个服务器上实现一致的系统配置,包括但不限......
  • 在Linux中,如何查看磁盘详细使用情况?
    在Linux系统中,查看磁盘详细使用情况主要有以下几个命令和工具:1.df命令df(diskfree)命令用于查看文件系统的总空间、已使用空间、剩余空间以及使用率等信息。以下是一些基本用法:#显示所有文件系统及其磁盘使用情况,以人类可读的格式(KB、MB、GB等)df-h#显示指定文件系统......