Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >从源码构建 perf

从源码构建 perf

作者头像
mazhen
发布于 2023-11-24 09:03:03
发布于 2023-11-24 09:03:03
1.6K00
代码可运行
举报
文章被收录于专栏:mazhen.techmazhen.tech
运行总次数:0
代码可运行

perfLinux 官方的性能分析工具,它具备 profiling、tracing 和脚本编写等多种功能,是内核 perf_events 子系统的前端工具。

perf_events 也被称为 Performance Counters for Linux (PCL) ,是在 2009 年合并到 Linux内核主线源代码中,成为内核一个新的子系统。perf_events 最初支持 performance monitoring counters (PMC) ,后来逐步扩展支持基于多种事件源,包括:tracepoints、kprobes、uprobes 和 USDT。

安装预编译二进制包

perf 包含在 linux-tools-common 中,首先安装该软件包:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ sudo apt install linux-tools-common

运行 perf 命令,可能会提示你安装另一个相关的软件包:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ perf
WARNING: perf not found for kernel 6.2.0-35

  You may need to install the following packages for this specific kernel:
    linux-tools-6.2.0-35-generic
    linux-cloud-tools-6.2.0-35-generic

  You may also want to install one of the following packages to keep up to date:
    linux-tools-generic
    linux-cloud-tools-generic

按照提示安装和内核版本相关的 package:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ sudo apt install linux-tools-6.2.0-35-generic

安装 Debug Symbol

perf 像其他调试工具一样,需要调试符号表信息(Debug symbols)。这些符号信息用于将内存地址转换为函数和变量名称。如果没有符号信息,你将看到代表被分析内存地址的十六进制数字。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
13.19%     0.00%  sshd             libc.so.6                    [.] __libc_start_call_main
            |
            ---__libc_start_call_main
               |          
                --12.91%--0x5641182e4b66
                          0x5641182fecf7
                          |          
                          |--9.50%--0x56411835c752
                          |          |          
                          |           --9.10%--0x5641183330dd
                          |                     |          
                          |                      --8.80%--0x5641182ee730
                          |                                |          
                          |                                |--4.64%--0x564118303c43

通过 package 方式安装的软件,一般都会提供以 -dbgsym-dbg 结尾的调试符号信息 package。在 Ubuntu 上,首先需要将-dbgsym 仓库添加到更新源中,执行下面的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
echo "deb http://ddebs.ubuntu.com $(lsb_release -cs) main restricted universe multiverse
deb http://ddebs.ubuntu.com $(lsb_release -cs)-updates main restricted universe multiverse
deb http://ddebs.ubuntu.com $(lsb_release -cs)-proposed main restricted universe multiverse" | \
sudo tee -a /etc/apt/sources.list.d/ddebs.list

然后从 Ubuntu 服务器导入调试符号 package 签名密钥:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ sudo apt install ubuntu-dbgsym-keyring

最后更新软件源,安装 glibc 和 openssh-server 的调试符号信息:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ sudo apt update
$ sudo apt install libc6-dbg
$ sudo apt install openssh-server-dbgsym

安装了调试符号信息后,再使用 perf report 就会将十六进制数字转换为对应的方法名:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
11.68%     0.00%  sshd             libc.so.6                 [.] __libc_start_call_main
            |
            ---__libc_start_call_main
               main
               |          
                --11.46%--do_authenticated
                          do_authenticated2 (inlined)
                          server_loop2.constprop.0
                          |          
                          |--8.30%--process_buffered_input_packets (inlined)
                          |          ssh_dispatch_run_fatal
                          |          ssh_dispatch_run (inlined)
                          |          |          
                          |           --7.86%--server_input_channel_req (inlined)
                          |                     |          
                          |                      --7.78%--session_input_channel_req (inlined)

我们还可以安装内核镜像和一些内置命令行工具的调试符号信息:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ sudo apt install coreutils-dbgsym
$ sudo apt install linux-image-`uname -r`-dbgsym

Kernel Tracepoints

Kernel tracepoint 是在内核源码中关键位置的埋点,允许开发人员监视内核中的各种事件和操作,例如系统调用、TCP事件、文件系统I/O、磁盘I/O等,以了解内核的行为,进行性能分析和故障诊断。

使用 perf 可以对 tracepoints 进行统计、追踪和采样。例如可以使用下面的命令对上下文切换进行 1 秒钟的跟踪:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ sudo perf record -e sched:sched_switch -a -g sleep 1

在执行这个命令的时候可能遇到下面的错误:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
event syntax error: 'sched:sched_switch'
                     \___ unsupported tracepoint

libtraceevent is necessary for tracepoint support
Run 'perf list' for a list of valid events

错误信息说明不支持 sched:sched_switch 这个 tracepoint。我们运行 perf list 查看可用的 tracepoint:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ sudo perf list 'sched:*'
List of pre-defined events (to be used in -e or -M):
...
  sched:sched_stat_wait                              [Tracepoint event]
  sched:sched_stick_numa                             [Tracepoint event]
  sched:sched_swap_numa                              [Tracepoint event]
  sched:sched_switch                                 [Tracepoint event]
  sched:sched_wait_task                              [Tracepoint event]
...

输出中明明包含了 sched:sched_switch,为什么 perf 不支持呢?

使用 perf version --build-options 查看 perf 的 build 选项:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ perf version --build-options
perf version 6.2.16
                 dwarf: [ on  ]  # HAVE_DWARF_SUPPORT
    dwarf_getlocations: [ on  ]  # HAVE_DWARF_GETLOCATIONS_SUPPORT
                 glibc: [ on  ]  # HAVE_GLIBC_SUPPORT
         syscall_table: [ on  ]  # HAVE_SYSCALL_TABLE_SUPPORT
                libbfd: [ OFF ]  # HAVE_LIBBFD_SUPPORT
            debuginfod: [ OFF ]  # HAVE_DEBUGINFOD_SUPPORT
                libelf: [ on  ]  # HAVE_LIBELF_SUPPORT
               libnuma: [ on  ]  # HAVE_LIBNUMA_SUPPORT
numa_num_possible_cpus: [ on  ]  # HAVE_LIBNUMA_SUPPORT
               libperl: [ OFF ]  # HAVE_LIBPERL_SUPPORT
             libpython: [ OFF ]  # HAVE_LIBPYTHON_SUPPORT
              libslang: [ on  ]  # HAVE_SLANG_SUPPORT
             libcrypto: [ on  ]  # HAVE_LIBCRYPTO_SUPPORT
             libunwind: [ on  ]  # HAVE_LIBUNWIND_SUPPORT
    libdw-dwarf-unwind: [ on  ]  # HAVE_DWARF_SUPPORT
                  zlib: [ on  ]  # HAVE_ZLIB_SUPPORT
                  lzma: [ on  ]  # HAVE_LZMA_SUPPORT
             get_cpuid: [ on  ]  # HAVE_AUXTRACE_SUPPORT
                   bpf: [ on  ]  # HAVE_LIBBPF_SUPPORT
                   aio: [ on  ]  # HAVE_AIO_SUPPORT
                  zstd: [ OFF ]  # HAVE_ZSTD_SUPPORT
               libpfm4: [ OFF ]  # HAVE_LIBPFM
         libtraceevent: [ OFF ]  # HAVE_LIBTRACEEVENT

libtraceevent 提供了访问内核 tracepoint 事件的 API。注意到最后一行,说明 perf 在 build 时没有打开 libtraceevent的支持。因此我们安装的预编译二进制包不能进行 tracepoint 追踪。我们需要自己从源码构建 perf。

从源码构建 perf

源码下载

首先下载 perf 的源代码。perf 的源码位于 Linux 内核源码中的 tools/perf 目录下。perf 是一个复杂的用户空间应用程序,而它却位于Linux 内核源代码树中,可能是唯一一个被包含在 Linux 源代码中的复杂用户软件。

为了下载和内核匹配的源码,先确定内核版本:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ uname -r
6.2.0-35-generic

然后去 https://www.kernel.org/pub/ 浏览并下载正确版本的源码。

安装依赖

安装构建依赖:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ sudo apt-get install build-essential flex bison python3 python3-dev
$ sudo apt-get install libelf-dev libnewt-dev libdw-dev libaudit-dev libiberty-dev libunwind-dev libcap-dev libzstd-dev libnuma-dev libssl-dev python3-dev python3-setuptools binutils-dev gcc-multilib liblzma-dev

我们需要支持 tracepoint,所以还要安装 libtraceevent package:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ sudo apt install libtraceevent-dev

构建

解压下载的 Linux 源码,进入源码目录,运行下面的命令:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ PYTHON=python3 make -C tools/perf install

成功构建后 perf 被安装到了 $HOME/bin 目录。

测试验证

卸载先前安装的预编译版本:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ sudo apt remove linux-tools-common

HOME/bin 加入到环境变量 PATH,确保我们构建的 perf 命令能被找到。注意一般我们都需要 sudo 执行 perf 命令,所以还要编辑 /etc/sudoers(必须使用 visudo)文件,在 Defaults secure_path="..." 中加入 perf 命令的路径。

验证 perf 的构建选项:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ sudo perf version --build-options
perf version 6.2.0
         ...
         libtraceevent: [ on  ]  # HAVE_LIBTRACEEVENT

这次 libtraceevent 打开了,支持 tracepoint 的追踪。执行下面的命令追踪系统的上下文切换:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ sudo perf record -e sched:sched_switch -a --call-graph dwarf  sleep 1

查看报告:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ sudo perf report
# To display the perf.data header info, please use --header/--header-only options.
#
#
# Total Lost Samples: 0
#
# Samples: 499  of event 'sched:sched_switch'
# Event count (approx.): 499
#
# Children      Self  Command          Shared Object               Symbol                               
# ........  ........  ...............  ..........................  .....................................
#
    48.70%    48.70%  swapper          [kernel.vmlinux]            [k] __schedule
            |
            ---secondary_startup_64_no_verify
               |          
               |--39.28%--start_secondary
               |          cpu_startup_entry
               |          do_idle
               |          schedule_idle
               |          __schedule
               |          __schedule
...

另外一个例子,按类型统计整个系统的系统调用,持续 5 秒钟:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ sudo perf stat -e 'syscalls:sys_enter_*' -a sleep 5

 Performance counter stats for 'system wide':

               ...         
                25      syscalls:sys_enter_timerfd_settime                                      
                 0      syscalls:sys_enter_timerfd_gettime                                      
                 0      syscalls:sys_enter_signalfd4                                          
                 0      syscalls:sys_enter_signalfd                                           
                 0      syscalls:sys_enter_epoll_create1                                      
                 0      syscalls:sys_enter_epoll_create                                       
                 0      syscalls:sys_enter_epoll_ctl                                          
                37      syscalls:sys_enter_epoll_wait                                         
                80      syscalls:sys_enter_epoll_pwait                                        
                 0      syscalls:sys_enter_epoll_pwait2                                       
                                         
                ...                                   

       5.004101037 seconds time elapsed

可以看到,我们自己 build 的 perf 可以对 tracepoint 进行追踪和统计。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-10-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
深入探索 perf CPU Profiling 实现原理
perf 是由 Linux 官方提供的系统性能分析工具 。我们通常说的 perf 实际上包含两部分:
mazhen
2023/11/24
3.4K2
深入探索 perf CPU Profiling 实现原理
系统级性能分析工具perf的介绍与使用[转]
测试环境:Ubuntu16.04(在VMWare虚拟机使用perf top存在无法显示问题)
sunsky
2020/08/20
3.6K0
系统级性能分析工具perf的介绍与使用[转]
perf和火焰图使用方法
perf是linux上的性能分析工具,perf可以对event进行统计得到event的发生次数,或者对event进行采样,得到每次event发生时的相关数据(cpu、进程id、运行栈等),利用这些数据来对程序性能进行分析。
嵌入式与Linux那些事
2023/03/24
4.1K0
perf和火焰图使用方法
包罗万象-perf命令介绍
大家好,我是程栩,一个专注于性能的大厂程序员,分享包括但不限于计算机体系结构、性能优化、云原生的知识。
程栩的性能优化笔记
2023/11/01
1.2K0
包罗万象-perf命令介绍
perf事件统计常用命令
Profiling # Sample on-CPU functions for the specified command, at 99 Hertz: perf record -F 99 command # Sample on-CPU functions for the specified PID, at 99 Hertz, until Ctrl-C: perf record -F 99 -p PID # Sample on-CPU functions for the specified PID, at
mingjie
2022/05/12
5870
bpf| 系统分析工具
eBPF is a revolutionary technology with origins in the Linux kernel that can run sandboxed programs in an operating system kernel. It is used to safely and efficiently extend the capabilities of the kernel without requiring to change kernel source code or load kernel modules.
heidsoft
2022/04/18
1.3K0
bpf| 系统分析工具
使用火焰图进行Java性能分析
内核维护着各种统计信息,被称为Counters,用于对事件进行计数。例如,接收的网络数据包数量,发出的磁盘I/O请求,执行的系统调用次数。常见的这类工具有:
mazhen
2023/11/24
1.4K0
使用火焰图进行Java性能分析
动态分析C语言代码生成函数调用关系的利器——perf
perf工具集并不默认安装在系统中,需要进行安装。(找到你系统匹配的版本,我的是linux-tools-5.15.0-91-generic)
方亮
2024/03/19
4430
动态分析C语言代码生成函数调用关系的利器——perf
linux tracepoint增加
内核采用“插桩”的方法抓取log,“插桩”也称为Tracepoint,Tracepoint是Linux内核预先定义的静态探测点,它分布于内核的各个子系统中,每种Tracepoint有一个name、一个enable开关、一系列桩函数、注册桩函数的函数、卸载桩函数的函数。“桩函数”功能类似于printk,不过“桩函数”并不会把信息打印到console,而是输出到内核的ring buffer(环形缓冲区),缓冲区中的信息通过debugfs对用户呈现。每个tracepoint提供一个钩子来调用probe函数。一个tracepoint可以打开或关闭。打开时,probe函数关联到tracepoint;关闭时,probe函数不关联到tracepoint。tracepoint关闭时对kernel产生的影响很小,只是增加了极少的时间开销(一个分支条件判断),极小的空间开销(一条函数调用语句和几个数据结构)。只有挂载了钩子函数才会真正启用trace功能。这个钩子函数可以由开发者编写内核module来实现,并且需要在钩子函数中获取我们调试所需要的信息并导出到用户态,这样就可以获取内核运行时的信息了。当一个tracepoint打开时,用户提供的probe函数在每次这个tracepoint执行都会被调用。
233333
2024/04/04
6410
linux tracepoint增加
程序员性能之道,从使用perf开始!
从2.6.31内核开始,Linux内核自带了一个性能分析工具perf,能够进行函数级与指令级的热点查找。通过它,应用程序可以利用 PMU,tracepoint 和内核中的特殊计数器来进行性能统计。它不但可以分析指定应用程序的性能问题 (per thread),也可以用来分析内核的性能问题,当然也可以同时分析应用代码和内核,从而全面理解应用程序中的性能瓶颈。
嵌入式Linux内核
2023/06/28
1.1K0
程序员性能之道,从使用perf开始!
万字长文解读 Linux 内核追踪机制
Linux 存在众多 tracing tools,比如 ftrace、perf,他们可用于内核的调试、提高内核的可观测性。众多的工具也意味着繁杂的概念,诸如 tracepoint、trace events、kprobe、eBPF 等,甚至让人搞不清楚他们到底是干什么的。本文尝试理清这些概念。
刘盼
2023/08/22
2.7K0
万字长文解读 Linux 内核追踪机制
强劲的Linux Trace工具:bpftrace (DTrace 2.0) for Linux 2018
译者注:原作者是大名鼎鼎的性能分析专家:Brendan Gregg,现在工作在Netflix,之前工作在Sun,在Sun公司的时候,他就做了大量的性能分析和tracing相关的工作,在Sun的Solaris上存在一种传说中的性能分析和Debug神器: Dtrace,然而,可惜的是,在我们现在的Linux操作系统上并没有Dtrace神器(这可能是因为Dtrace是从Soloris操作系统的衍生品无法迁移到别的操作系统上),Brendan Gregg 在Netflix后,继续利用他的业余时间,利用他曾经在Soloris上的性能分析经验,和对Dtrace工具的理解,研发基于Linux操作系统上的上类似于Dtrace的工具,曾经他在早期的kernel版本上基于perf研发了perf-tools工具,后面在eBPF进入kernel后,开始基于eBPF做性能工具研发的工作,比如bcc工具集,最近又参与了bpftrace的工具。本文主要是Brendan Gregg在介绍 bpftrace在2018年的开发进展,以及对bpftrace的介绍和对Dtrace的区别介绍。
Linux阅码场
2019/06/04
6.2K0
强劲的Linux Trace工具:bpftrace (DTrace 2.0) for Linux 2018
从小白到精通:揭秘perf工具的全部功能与操作技巧
perf工具是Linux操作系统下的一款性能分析工具,主要用于分析程序的性能瓶颈和优化程序的性能。它可以快速定位和解决系统性能问题,提高程序的运行效率和稳定性。
Lion 莱恩呀
2024/11/03
1.2K0
从小白到精通:揭秘perf工具的全部功能与操作技巧
从Ftrace开始内核探索之旅
操作系统内核对应用开发工程师来说就像一个黑盒,似乎很难窥探到其内部的运行机制。其实Linux内核很早就内置了一个强大的tracing工具:Ftrace,它几乎可以跟踪内核的所有函数,不仅可以用于调试和分析,还可以用于观察学习Linux内核的内部运行。虽然Ftrace在2008年就加入了内核,但很多应用开发工程师仍然不知道它的存在。本文就给你介绍一下Ftrace的基本使用。
mazhen
2023/11/24
7280
从Ftrace开始内核探索之旅
【云原生技术研究】 从bpftrace看如何利用eBPF实现内核追踪
bpftrace提供了一种快速利用eBPF实现动态追踪的方法,可以作为简单的命令行工具或者入门级编程工具来使用。本文以bpftrace为例,介绍如何利用eBPF实现内核的动态追踪。
绿盟科技研究通讯
2020/09/01
2.5K0
【云原生技术研究】 从bpftrace看如何利用eBPF实现内核追踪
原创Paper | 在 Android 中开发 eBPF 程序学习总结(一)
其实是想学习一下ecapture是怎么实现的,但是实际在我xiaomi 10手机上测试的过程中(已经有root权限)发现,并没办法运行,因为ecapture需要内核开启CONFIG_DEBUG_INFO_BTF,这个配置信息可以通过/proc/config.gz中来查看是否开启。
Seebug漏洞平台
2023/01/05
2.3K0
如何利用eBPF程序监控Kubernetes
对 Kubernetes 集群进行监控对于确保容器化应用程序的健康、性能和可靠性至关重要。Kubernetes 提供了强大的监控工具套件和集成,但是当您需要深入内核和网络级别的复杂性时,eBPF(扩展的伯克利包过滤器)就成为了无价的资源。在本文中,我们将探索惊人的 eBPF 功能,以及如何利用它提升 Kubernetes 监控策略。
云云众生s
2024/03/28
2770
如何利用eBPF程序监控Kubernetes
C++ 之 perf+火焰图分析与调试
在遇到一些内存异常的时候,经常这部分的代码是很难去进行分析的,最近了解到Perf这个神器,这里也展开介绍一下如何使用Perf以及如何去画火焰图。
芯动大师
2024/09/10
2590
C++ 之 perf+火焰图分析与调试
从Falco看如何利用eBPF检测系统调用
eBPF是一项革命性的技术,可以在操作系统内核中运行沙盒程序。它用于安全有效地扩展内核的功能,而无需更改内核源代码或加载内核模块。通过允许在操作系统中运行沙箱程序,应用程序开发人员可以运行eBPF程序,以便在运行时向操作系统添加额外的功能。然后,操作系统保证安全性和执行效率,就像在实时(JIT)编译器和验证引擎的帮助下进行本机编译一样。这导致了一波基于eBPF的项目,涵盖了广泛的用例,包括下一代网络、可观察性和安全功能。
绿盟科技研究通讯
2022/06/06
2.9K0
从Falco看如何利用eBPF检测系统调用
Perf分析CPU性能问题笔记
容器内的进程实际上可以在host machine上看到,ps -ef | grep <text>可以找得到。
颇忒脱
2019/04/21
6.2K0
相关推荐
深入探索 perf CPU Profiling 实现原理
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验