性能分析的方法论
Linux 系统性能问题的排查不是靠”感觉”,而是靠一套系统的方法论。Brendan Gregg(Netflix 高级性能架构师)提出的 USE 方法和 Linux 性能工具图谱是行业标准。
USE 方法
对每一个资源,检查:
- Utilization(利用率):资源忙于工作的时间比例
- Saturation(饱和度):资源排队等待的程度
- Errors(错误):资源的错误计数
资源包括:CPU、内存、磁盘 IO、网络、文件描述符、内核连接等。
性能分析的层次
1 2 3 4 5 6 7 8 9
| 应用层 → 应用代码、算法、数据库查询 ↓ 运行时层 → JVM/Node/Python GC、线程池、连接池 ↓ 系统调用层 → syscall 频率、延迟、错误 ↓ 内核层 → 调度器、内存管理、网络栈、IO 栈 ↓ 硬件层 → CPU 缓存、内存带宽、磁盘、网卡
|
性能问题可能出现在任何一层,需要从上层往下逐层排查。
CPU 性能分析
1. 整体 CPU 状况
1 2 3 4 5 6 7 8 9 10 11 12 13
| uptime
vmstat 1 3
mpstat -P ALL 1
top -H pidstat 1 pidstat -t 1
|
2. CPU 性能指标解读
vmstat 输出的关键列:
r:运行队列长度(正在运行 + 等待 CPU 的进程数)。如果持续大于 CPU 核心数,说明 CPU 饱和
us:用户态 CPU 时间百分比
sy:内核态 CPU 时间百分比。如果 sy 很高(>20%),说明系统调用或内核操作频繁
wa:IO 等待时间。如果 wa 很高,说明 CPU 在等磁盘 IO,瓶颈在磁盘而不是 CPU
id:空闲时间
3. CPU 火焰图
火焰图是分析 CPU 性能的最强大工具,可以直观看到 CPU 时间花在了哪些函数上。
1 2 3 4 5 6 7 8 9
| perf record -F 99 -a -g -- sleep 30 perf script > out.perf
git clone https://github.com/brendangregg/FlameGraph stackcollapse-perf.pl out.perf | flamegraph.pl > flamegraph.svg
|
火焰图的读法:
- 横轴:采样数量(代表 CPU 时间占比),越宽表示占用 CPU 越多
- 纵轴:调用栈深度,从下到上是调用关系
- 点击某个方块可以放大查看细节
4. 调度器分析
1 2 3 4 5 6 7 8
| cat /proc/schedstat
pidstat -d 1
vmstat 1
|
如果上下文切换频率很高(>10000/s),可能是:
- 线程数过多
- 锁竞争激烈
- IO 频繁导致线程阻塞/唤醒
5. CPU 调优
1 2 3 4 5 6 7 8 9 10 11 12
| cpupower frequency-set -g performance
taskset -c 0,1,2,3 ./myapp
echo off > /sys/devices/system/cpu/smt/control
|
内存性能分析
1. 整体内存状况
1 2 3 4 5 6 7 8 9 10
| free -h
cat /proc/meminfo
ps aux --sort=-%mem | head -20 pmap -x <pid> smem -tk
|
2. 关键内存指标
MemAvailable:真正可用的内存(不是 MemFree,因为 Linux 会用空闲内存做缓存)
SwapUsed:如果 swap 使用量持续增长,说明物理内存不足
Dirty:等待写回磁盘的脏页。如果很高,说明磁盘写入跟不上
PageTables:页表占用的内存。如果很高(>1GB),可能是内存碎片或进程过多
Slab:内核 slab 分配器占用的内存(dentry、inode 等缓存)
3. 内存泄漏检测
1 2 3 4 5 6 7 8 9 10 11 12
| valgrind --leak-check=full --show-leak-kinds=all ./myapp
LD_PRELOAD=/usr/lib/libtcmalloc.so HEAPPROFILE=./heap ./myapp pprof --pdf ./myapp heap.0001.heap > heap.pdf
bpftrace -e 'uprobe:/lib/x86_64-linux-gnu/libc.so.6:malloc { @[ustack]=count(); }'
watch -n 1 'ps -o pid,rss,vsz,comm -p <pid>'
|
4. Swap 调优
1 2 3 4 5 6 7 8
| cat /proc/sys/vm/swappiness
echo 1 > /proc/sys/vm/swappiness
echo 'vm.swappiness = 1' >> /etc/sysctl.conf
|
5. 大页(HugePages)
对于内存密集型应用(数据库、Java),大页可以减少 TLB miss:
1 2 3 4 5 6 7 8 9 10
| cat /proc/meminfo | grep Huge
echo 1000 > /proc/sys/vm/nr_hugepages
echo never > /sys/kernel/mm/transparent_hugepage/enabled echo never > /sys/kernel/mm/transparent_hugepage/defrag
|
磁盘 IO 性能分析
1. 整体 IO 状况
1 2 3 4 5 6 7 8 9
| iostat -xz 1 3
pidstat -d 1 iotop -o
iostat -x 1
|
2. 关键 IO 指标
r/s、w/s:每秒读/写次数(IOPS)
rkB/s、wkB/s:每秒读/写数据量(吞吐量)
await:平均 IO 延迟(队列等待 + 设备服务时间)。SSD 应 <1ms,HDD 应 <10ms
%util:设备繁忙时间百分比。如果持续 >80%,说明磁盘可能是瓶颈
aqu-sz:平均队列深度。如果很高,说明 IO 在排队
3. IO 延迟分析
1 2 3 4 5 6 7 8
| biolatency -m 10 1
biosnoop -Q 10
filetop -C 1 10
|
4. 磁盘调优
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| cat /sys/block/sda/queue/scheduler
echo mq-deadline > /sys/block/sda/queue/scheduler
echo 256 > /sys/block/sda/queue/nr_requests
blockdev --setra 4096 /dev/sda
mount -o noatime,data=writeback /dev/sda1 /mnt
|
网络性能分析
1. 整体网络状况
1 2 3 4 5 6 7 8 9 10 11 12 13
| ip -s link ifconfig -s
ss -s ss -tlnp ss -ti
iftop -i eth0 nload eth0 vnstat -i eth0
|
2. TCP 性能指标
1 2 3
| nstat -az | grep Tcp cat /proc/net/snmp | grep Tcp
|
关键指标:
TcpRetransSegs:重传段数。重传率 >0.1% 说明网络有问题
TcpExtListenOverflows:监听队列溢出。如果增长,说明应用 accept 太慢或 backlog 太小
TcpExtTCPSynRetrans:SYN 重传。三次握手失败
TcpExtTCPTimeouts:TCP 超时
3. 网络延迟分析
1 2 3 4 5 6 7 8 9 10 11 12 13
| ping -c 10 target.com
mtr --report target.com traceroute target.com
curl -o /dev/null -s -w "TCP连接: %{time_connect}s\nTLS握手: %{time_appconnect}s\n首字节: %{time_starttransfer}s\n总时间: %{time_total}s\n" https://target.com
tcplife -T tcpconnlat 1 10
|
4. 网络调优
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| echo 4096 > /proc/sys/net/core/somaxconn echo 4096 > /proc/sys/net/ipv4/tcp_max_syn_backlog
echo 'net.core.rmem_max = 16777216' >> /etc/sysctl.conf echo 'net.core.wmem_max = 16777216' >> /etc/sysctl.conf echo 'net.ipv4.tcp_rmem = 4096 87380 16777216' >> /etc/sysctl.conf echo 'net.ipv4.tcp_wmem = 4096 65536 16777216' >> /etc/sysctl.conf
echo bbr > /proc/sys/net/ipv4/tcp_congestion_control echo 'net.core.default_qdisc = fq' >> /etc/sysctl.conf
echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout
echo '* soft nofile 65535' >> /etc/security/limits.conf echo '* hard nofile 65535' >> /etc/security/limits.conf
|
eBPF 性能工具
eBPF 是现代 Linux 性能分析的利器,可以在内核态高效收集数据,不需要重新编译内核。
常用 eBPF 工具(BCC / bpftrace)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| sudo apt install bpfcc-tools linux-headers-$(uname -r)
syscount -p <pid> 1 10
funclatency -u do_sys_open 1 10
execsnoop -T
opensnoop -p <pid>
tcpretrans -l
pagefaults -p <pid> 1 10
runqlat -m 1 10
mutexlock -p <pid> 1 10
|
bpftrace 一行命令
1 2 3 4 5 6 7 8
| bpftrace -e 'tracepoint:syscalls:sys_enter_execve { printf("%s: %s\n", comm, str(args->filename)); }'
bpftrace -e 'tracepoint:syscalls:sys_enter_* { @[probe] = count(); } interval:s:10 { print(@); clear(@); }'
bpftrace -e 'kprobe:do_sys_open { @start[tid] = nsecs; } kretprobe:do_sys_open /@start[tid]/ { $dur = (nsecs - @start[tid]) / 1000000; if ($dur > 10) { printf("%s: %dms\n", comm, $dur); } delete(@start[tid]); }'
|
性能基准测试
CPU 基准
1 2 3 4 5 6 7 8
| time make -j$(nproc)
7z b
sysbench cpu --cpu-max-prime=20000 run
|
内存基准
1 2 3 4 5
| sysbench memory --memory-block-size=1M --memory-total-size=10G run
lmbench/lat_mem_rd 100M 512
|
磁盘基准
1 2 3 4 5 6 7 8
| fio --name=read --filename=/dev/sda --rw=read --bs=1M --direct=1 --iodepth=32 --runtime=60
fio --name=randrw --filename=/dev/sda --rw=randrw --rwmixread=70 --bs=4k --direct=1 --iodepth=32 --runtime=60 --numjobs=4
fio --name=latency --filename=/dev/sda --rw=randread --bs=4k --direct=1 --iodepth=1 --runtime=60
|
网络基准
1 2 3 4 5 6 7 8 9 10 11
|
iperf3 -s
iperf3 -c server_ip -t 60 -P 4
ping -c 100 -i 0.2 server_ip
wrk -t4 -c100 -d30s https://target.com
|
性能问题排查清单
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| 系统慢? │ ├─ CPU 高? │ ├─ us 高 → 应用代码问题,用火焰图分析 │ ├─ sy 高 → 系统调用频繁,用 strace/syscount 分析 │ ├─ wa 高 → 磁盘 IO 瓶颈,看 iostat │ └─ si/hi 高 → 中断处理,看 /proc/interrupts │ ├─ 内存不足? │ ├─ swap 使用增长 → 物理内存不足,找内存泄漏 │ ├─ OOM killer 触发 → dmesg | grep oom │ └─ 缓存占用高 → 正常,Linux 会用空闲内存做缓存 │ ├─ 磁盘慢? │ ├─ %util > 80% → 磁盘饱和 │ ├─ await 高 → IO 延迟大 │ └─ 队列深 → 应用 IO 太多或磁盘太慢 │ ├─ 网络慢? │ ├─ 重传率高 → 网络质量差 │ ├─ 连接队列溢出 → 应用 accept 慢或 backlog 小 │ ├─ TIME_WAIT 多 → 短连接太多,考虑长连接/连接池 │ └─ 带宽打满 → 流量过大 │ └─ 都不高但还是慢? ├─ 锁竞争 → perf lock / mutexlock ├─ 调度延迟 → runqlat ├─ 数据库慢查询 → 开启慢查询日志 └─ 应用层问题 → 应用性能分析(APM)
|
总结
Linux 性能分析是一门系统性的工程,需要掌握从硬件到应用的全栈知识。核心方法论是:
- USE 方法:对每个资源检查利用率、饱和度、错误
- 从整体到局部:先看整体资源状况,再深入到具体进程和函数
- 用数据说话:不要靠感觉,用工具收集准确的性能数据
- 火焰图:CPU 性能分析的首选工具
- eBPF:现代 Linux 性能分析的利器,可以深入内核态收集数据
性能调优的关键是找到真正的瓶颈,而不是盲目调参数。很多性能问题的根因在应用层(慢查询、算法低效、内存泄漏),而不是系统层。先定位瓶颈,再有针对性地调优,才能事半功倍。