Linux Perf

Table of Contents

1. 参考链接

2. 多线程优化

Performance analysis of multithreaded applications. | Easyperf https://easyperf.net/blog/2019/10/05/Performance-Analysis-Of-MT-apps

How to find expensive locks in multithreaded application. | Easyperf https://easyperf.net/blog/2019/10/12/MT-Perf-Analysis-part2

Detect false sharing with Data Address Profiling. | Easyperf https://easyperf.net/blog/2019/12/17/Detecting-false-sharing-using-perf

C2C - False Sharing Detection in Linux Perf - My Octopress Blog https://joemario.github.io/blog/2016/09/01/c2c-blog/

caching - Is it possible to know the address of a cache miss? - Stack Overflow https://stackoverflow.com/questions/23736999/is-it-possible-to-know-the-address-of-a-cache-miss/45899495#45899495

https://www.brendangregg.com/perf.html#SchedulerAnalysis

perf查看内存访问情况

  • `perf mem record – <process>` 对内存访问进行采样
  • `perf mem report –stdio` 查看每个内存地址的访问频率和延迟
  • `perf mem -t load/store report –sort=mem –stdio` 针对load/store查看内存层次上的次数和延迟

perf分析单个线程情况

  • `perf record -s` 对每个线程分别进行采样
  • `perf report -n -T` 对线程进行group by分析
  • `perf report -T –tid 6607 -n` 针对某个线程进行单独分析
  • `perf record -s -e sched:sched_switch -g –call-graph dwarf` 对线程切换进行分析(需要存储调用堆栈)
  • `perf report -n –stdio –no-call-graph -T` (然后在阅读的时候把堆栈省略)

perf查看cache之间冲突 (https://joemario.github.io/blog/2016/09/01/c2c-blog/)

  • `perf c2c record –all-user/-u –ldlat 50` 收集用户态的cache冲突,并且load时间超过50cycles才会上报
  • TODO: 需要具体场景来使用

3. 常见问题

3.1. 确保perf版本和内核版本匹配

sandbox-sql :: ~/work/run-bench ‹master› » uname -r
3.10.0-1160.42.2.el7.x86_64
sandbox-sql :: ~/work/run-bench ‹master› » perf -v
perf version 3.10.0-1160.42.2.el7.x86_64.debug

某些情况下内核会自动升级(可能也是执行了yum update时候触发的),从我的经验来看就会在/boot目录下面产生多个启动配置

sandbox-sql :: ~/work/run-bench ‹master› » ls /boot/config-3.10.0-11* -l
-rw-r--r--  1 root root 153567 Aug 26  2020 /boot/config-3.10.0-1127.19.1.el7.x86_64
-rw-r--r--. 1 root root 153562 Apr  1  2020 /boot/config-3.10.0-1127.el7.x86_64
-rw-r--r--  1 root root 153596 Sep  7 22:54 /boot/config-3.10.0-1160.42.2.el7.x86_64
sandbox-sql :: ~/work/run-bench ‹master› » ls /boot/initramfs-* -l
-rw-------. 1 root root 58572648 Sep 14  2020 /boot/initramfs-0-rescue-20200914151306980406746494236010.img
-rw-------  1 root root 17784907 Sep 18 10:54 /boot/initramfs-3.10.0-1127.19.1.el7.x86_64.img
-rw-------  1 root root 10733878 Sep 14  2020 /boot/initramfs-3.10.0-1127.19.1.el7.x86_64kdump.img
-rw-------  1 root root 18199672 Sep 14  2020 /boot/initramfs-3.10.0-1127.el7.x86_64.img
-rw-------  1 root root 10731212 Sep 14  2020 /boot/initramfs-3.10.0-1127.el7.x86_64kdump.img
-rw-------  1 root root 17785753 Sep 18 10:53 /boot/initramfs-3.10.0-1160.42.2.el7.x86_64.img

如果发现内核和perf版本不同的话,那么可能就需要重启机器了,版本不同很多PMU/hardward events就没有办法使用。

为了避免系统自动更新,可以使用这篇文章的方法 CentOS 7禁止内核自动更新升级 LiuJason'sBlog

执行更新的时候加上exclude参数 `sudo yum –exclude=kernel* update`

或者是在 `/etc/yum.conf` 文件里面 [main] section里面增加

#禁止更新内核
exclude=kernel*
# 禁止更新系统
exclude=centos-release*

3.2. 调试perf版本时yum几个命令

使用所有仓库查看可用的perf

yum –enablerepo="**" list available perf

查看不同版本的perf

yum –enablerepo="**" –showduplicates list available perf

只在某些特定仓库下查找

yum –enablerepo="centos-kernel,centos-sclo-rh,fasttrack" –showduplicates search perf

列举所有的仓库

yum repolist

3.3. 反编译和符号解析问题

最近跑perf想看某个符号的汇编代码总是失败,我想到这个是不是和objdump有关系,因为objdump就是用来做反汇编的。

用系统自带的objdump出现下面这个错误

sandbox-sql :: ~/DorisDB ‹ext-planner-profile› » objdump -d ./output/be/lib/starrocks_be
objdump: ./output/be/lib/starrocks_be: unable to initialize decompress status for section .debug_aranges
objdump: ./output/be/lib/starrocks_be: unable to initialize decompress status for section .debug_aranges
objdump: ./output/be/lib/starrocks_be: File format not recognized

google了一下这个问题,发现golang社区也有,https://github.com/golang/go/issues/42136 就是因为使用了低版本的binutils. 然后对于某一类最新编译的section无法解析导致的,升级到bintuils-2.32就能解决这个问题。 https://centos.pkgs.org/7/centos-sclo-rh-x86_64/devtoolset-9-binutils-2.32-14.el7.x86_64.rpm.html

  • yum install centos-release-scl-rh
  • yum install devtoolset-9-binutils
sandbox-sql :: ~/DorisDB ‹ext-planner-profile› » /opt/rh/devtoolset-9/root/usr/bin/objdump -d ./output/be/lib/starrocks_be > x
sandbox-sql :: ~/DorisDB ‹ext-planner-profile*› » head x

./output/be/lib/starrocks_be:     file format elf64-x86-64


Disassembly of section .plt:

00000000022de000 <JNI_CreateJavaVM@plt-0x10>:
 22de000:       ff 35 02 50 38 04       pushq  0x4385002(%rip)        # 6663008 <_GLOBAL_OFFSET_TABLE_+0x8>
 22de006:       ff 25 04 50 38 04       jmpq   *0x4385004(%rip)        # 6663010 <_GLOBAL_OFFSET_TABLE_+0x10>
 22de00c:       0f 1f 40 00             nopl   0x0(%rax)

接着问题就是如何让perf使用这个objdump, 修改一下PATH就好了: `export PATH=/opt/rh/devtoolset-9/root/usr/bin/:$PATH`

3.4. flamegraph和perf结果差异

http://smalldatum.blogspot.com/2022/04/i-previously-wrote-about-generating.html

https://github.com/brendangregg/FlameGraph/issues/165

目前flamegraph在解析-F的时候,没有把sample period考虑进去,所以导致flamegraph和perf report结果是不一致的。

这个区别至今不是特别理解,总之就是如果在解释的时候出现什么问题的话,可以考虑使用-c而不是-F重新进行profile