性能调优

本文最后更新于:2024年8月27日 上午

性能调优

性能优化

ltrace

strace

ftrace

ftrace hook

perf

perf 基本使用

1
cd ~/byte-unixbench-5.1.3/UnixBench

perf record

1
2
3
4
5
6
7
8
9
10
11
12
13
perf record pgms/fstime -c -t 30 -d tmp -b 1024 -m 2000

Write done: 14920000 in 2.0003, score 1864695
COUNT|1864695|0|KBps
TIME|2.0
Read done: 19222004 in 2.0000, score 2402736
COUNT|2402736|0|KBps
TIME|2.0
Copy done: 109794984 in 30.0000, score 914957
COUNT|914957|0|KBps
TIME|30.0
[ perf record: Woken up 21 times to write data ]
[ perf record: Captured and wrote 5.193 MB perf.data (136007 samples) ]
1
2
3
4
5
6
7
8
9
perf report

Samples: 136K of event 'cpu-clock', Event count (approx.): 34001750000
Overhead Command Shared Object Symbol
15.14% fstime [kernel.kallsyms] [k] __arch_copy_to_user
8.07% fstime [kernel.kallsyms] [k] el0_svc_common
7.72% fstime [kernel.kallsyms] [k] __arch_copy_from_user
7.13% fstime libc.so.6 [.] read
6.77% fstime libc.so.6 [.] write

perf report 输出中,数据的各列信息如下:

  • Overhead:表示每个函数在所有采样中占用的 CPU 时间百分比。
  • Command:表示执行该函数的命令或进程名(例如 fstime)。
  • Shared Object:表示函数所在的共享库或二进制文件(例如 [kernel.kallsyms] 表示内核,libc.so.6 表示 C 标准库)。
  • Symbol:表示函数的名称(例如 __arch_copy_to_userreadwrite)。
简单总结
  • __arch_copy_to_user:占用 15.14% 的 CPU 时间。
  • el0_svc_common:占用 8.07% 的 CPU 时间。
  • __arch_copy_from_user:占用 7.72% 的 CPU 时间。
  • read:占用 7.13% 的 CPU 时间。
  • write:占用 6.77% 的 CPU 时间。
20240819142952
选择某一行深入分析

移动键盘上下键选择第一行__arch_copy_to_user,然后按enter。

__arch_copy_to_user
1
2
3
4
5
6
7
Annotate __arch_copy_to_user
Zoom into fstime thread
Zoom into the Kernel DSO
Browse map details
Run scripts for samples of symbol [__arch_copy_to_user]
Run scripts for all samples
Switch to another data file in PWD

perf report 中,可以执行以下操作:

  • Annotate __arch_copy_to_user:查看 __arch_copy_to_user 函数的汇编代码级别性能注释。
  • Zoom into fstime thread:查看 fstime 线程的详细性能数据。
  • Zoom into the Kernel DSO:查看内核共享对象的详细性能数据。
  • Browse map details:查看地址映射的详细信息。
  • Run scripts for samples of symbol [__arch_copy_to_user]:对 __arch_copy_to_user 符号的样本运行分析脚本。
  • Run scripts for all samples:对所有样本运行分析脚本。
  • Switch to another data file in PWD:切换到当前目录中的另一个数据文件。
Kernel DSO

perf report 中,Kernel DSO(Dynamic Shared Object)指的是内核的共享对象或模块,它是内核的运行时组件。具体来说:

  • Kernel DSO:在内核空间中,虽然内核本身不是一个传统意义上的共享库,但内核的功能和符号可以被视作类似于动态共享对象。在性能分析中,Kernel DSO 表示内核的各个部分(如模块、驱动程序等),这些部分在执行期间动态地被加载到内存中。

  • 使用场景:在性能分析中,你可以查看 Kernel DSO 的详细数据,以了解内核模块或驱动程序的性能表现,找出性能瓶颈或潜在问题。

简单总结

  • Kernel DSO 是指在内核空间动态加载的共享对象或模块,用于分析内核部分的性能。

perf record -F 99 -g

1
2
3
4
5
6
7
8
9
10
11
12
13
perf record -F 99 -g pgms/fstime -c -t 30 -d tmp -b 1024 -m 2000

Write done: 14688000 in 2.0005, score 1835538
COUNT|1835538|0|KBps
TIME|2.0
Read done: 19491392 in 2.0000, score 2436409
COUNT|2436409|0|KBps
TIME|2.0
Copy done: 110976628 in 30.0000, score 924804
COUNT|924804|0|KBps
TIME|30.0
[ perf record: Woken up 3 times to write data ]
[ perf record: Captured and wrote 0.529 MB perf.data (3366 samples) ]
  • -F 99:设置采样频率为 99 Hz。
  • -g:捕获调用栈信息。
1
2
3
4
5
6
7
8
9
perf report

Samples: 3K of event 'cpu-clock', Event count (approx.): 33999999660
Children Self Command Shared Object Symbol
+ 100.00% 0.00% fstime fstime [.] _start
+ 100.00% 0.00% fstime libc.so.6 [.] __libc_start_main
+ 87.67% 1.84% fstime fstime [.] c_test
+ 82.86% 0.00% fstime [kernel.kallsyms] [k] el0_svc
+ 82.86% 0.00% fstime [kernel.kallsyms] [k] el0_svc_handler

perf report 中各列的含义如下:

  1. Children:函数及其子函数的总 CPU 时间占比。
  2. Self:函数自身的 CPU 时间占比。
  3. Command:执行的命令或进程名。
  4. Shared Object:函数所在的库或二进制文件。
  5. Symbol:函数名称。
perf record -F 99 -g pgms/fstime -c -t 30 -d tmp -b 1024 -m 2000 perf report

性能采集小工具

获取自制性能采集小工具:

1
2
3
sudo wget -P /usr/local/bin https://raw.githubusercontent.com/realwujing/realwujing.github.io/main/debug/bpf/perf.sh
sudo chmod +x /usr/local/bin/perf.sh
sudo wget -P /etc/systemd/system https://raw.githubusercontent.com/realwujing/realwujing.github.io/main/debug/bpf/perf.service

重新加载systemd配置:

1
sudo systemctl daemon-reload

开机自动启动且立马启动性能采集服务:

1
sudo systemctl enable --now perf.service

查看性能采集服务状态:

1
sudo systemctl status perf.service

查看性能采集服务日志:

1
sudo journalctl -fxeu perf.service

关闭性能采集服务:

1
sudo systemctl stop perf.service

禁止性能采集服务开机自动启动:

1
sudo systemctl disable perf.service

收集日志:

/var/log:系统日志

/var/log/iostat:实时报告系统的磁盘 I/O 统计信息

/var/log/pidstat:找到 IO 占用高的进程

/var/log/top:实时报告系统的进程资源占用

/var/log/perf:实时报告系统的性能热点

perf实践

hcache

eBPF

bpftrace

1
bpftrace -e 'tracepoint:signal:signal_generate { printf("Process %d %s send SIGNAL %d to process %d %s\n", pid, comm, args->sig, args->pid, args->comm); }'

您提供的命令是使用 bpftrace 工具来跟踪信号生成事件,并打印相关信息。让我解释一下这个命令的含义:

bpftrace:是一个强大的跟踪和探查工具,它使用BPF(Berkley Packet Filter)技术来提供对内核和用户空间的动态跟踪能力。

-e:这是 bpftrace 命令的选项,用于指定要执行的跟踪程序。

'tracepoint:signal:signal_generate { printf("Process %d %s send SIGNAL %d to process %d %s", pid, comm, args->sig, args->pid, args->comm); }':这是要执行的 bpftrace 跟踪程序。

跟踪程序的含义是:当信号生成事件(signal_generate)发生时,打印相关信息。具体来说,它打印了发送信号的进程的进程ID(pid)、进程名称(comm),以及接收信号的进程的进程ID(args->pid)和进程名称(args->comm)。

这个命令可以帮助您跟踪信号的生成情况,并提供有关发送和接收信号的进程信息。您可以根据需要修改打印的信息或添加其他的跟踪逻辑来满足您的需求。请注意,使用 bpftrace 跟踪程序需要在支持BPF的内核版本上运行,并具有足够的权限。

SIGTERM

专门追踪信号:SIGTERM (15):

1
bpftrace -e 'tracepoint:signal:signal_generate /args->sig == 15/ { printf("Process %d %s send SIGNAL %d to process %d %s\n", pid, comm, args->sig, args->pid, args->comm); }'

专门追踪信号:SIGTERM (15)并输出到sigterm.log:

1
bpftrace -e 'tracepoint:signal:signal_generate /args->sig == 15/ { printf("Process %d %s send SIGNAL %d to process %d %s\n", pid, comm, args->sig, args->pid, args->comm); }' | tee sigterm.log

oom

追踪OOM Killer事件:

1
bpftrace --include 'linux/oom.h' -e 'kprobe:oom_kill_process {printf("triggered by pid :%d, comm: %s, oom kill of pid: %d, comm: %s\n", pid, comm, ((struct oom_control *)arg1)->chosen->pid, ((struct oom_control *)arg1)->chosen->comm)}'

追踪kprobe:vhost_work_queue:

1
2
3
yum install kernel-debugsource-4.19.90-2102.2.0.0066.ctl2.x86_64 -y
rpm -ql kernel-debugsource-4.19.90-2102.2.0.0066.ctl2.x86_64 | grep vhost.h
bpftrace --include '/usr/src/debug/kernel-4.19.90-2102.2.0.0066.ctl2.x86_64/linux-4.19.90-2102.2.0.0066.ctl2.x86_64/drivers/vhost/vhost.h' -e 'kprobe:vhost_work_queue {printf("fn:%lx\n", ((struct vhost_work *)arg1)->fn);}'

pstack

method tracing

Grafana

安装环境:

1
sudo apt install grafana prometheus prometheus-**alertmanager**

由于主机9090端口被占用,故通过systemd启动prometheus时需要更改一下端口为9999:

1
2
3
4
5
6
cat /etc/default/prometheus | head -n5
# Set the command-line arguments to pass to the server.
ARGS=""--web.listen-address="127.0.0.1:9999"

# Prometheus supports the following options:
# --config.file="/etc/prometheus/prometheus.yml"

开启自启:

1
2
sudo systemctl daemon-reload
sudo systemctl enable --now grafana-server.service prometheus.service prometheus-alertmanager.service

登录grafana:

1
http://localhost:3000 # 初始账号密码都是admin

Add your first data source:

选择Prometheus

Connection

Prometheus server URL *填入下方url:

1
http://localhost:9999

跳到最下方点击Save & test即可。

Create your first dashboard:

Import dashboard填入下方链接(本机为deepin 20.9,不支持最新版本的Node Exporter Full,建议使用下方链接):

1
https://grafana.com/api/dashboards/1860/revisions/22/download

也可通过id导入,建议id:

1
2
3
4
5
1860
10842
8919
15172
2747

prometheus-alertmanager暂未配置。

unixbench


性能调优
https://realwujing.github.io/linux/debug/bpf/性能调优/
作者
Wu Jing
发布于
2024年7月23日
许可协议