系统性能调优
性能分析方法论
USE 方法 (Brendan Gregg)
对于每个资源,检查:Utilization(利用率)、Saturation(饱和度)、Errors(错误)
| 资源 | 利用率 | 饱和度 | 错误 |
|---|---|---|---|
| CPU | CPU 使用率 | 运行队列长度 | 无 |
| 内存 | 内存使用率 | OOM、Swap 使用 | 无 |
| 磁盘 | 磁盘 I/O 利用率 | I/O 等待队列 | 磁盘错误 |
| 网络 | 带宽使用率 | 丢包、缓冲区溢出 | 网卡错误 |
CPU 调优
监控命令
# 实时 CPU 使用
top - 1 # 按 1 查看每个核心
htop # 增强版
mpstat -P ALL 1 # 每个 CPU 的详细统计
# CPU 负载
uptime # 负载平均值
cat /proc/loadavg
# 上下文切换
vmstat 1 5 # cs 列是上下文切换
pidstat -w 1 # 查看进程的上下文切换
# 运行队列
sar -q 1 5 # runq-sz 是队列长度
优化策略
# 1. 调整进程调度策略
# 实时进程使用 SCHED_FIFO 或 SCHED_RR
chrt -f 10 ./realtime-app
# 2. 设置 CPU 亲和性
taskset -c 0,1 ./app # 绑定到 CPU 0 和 1
# 3. 内核参数
# /etc/sysctl.d/99-cpu.conf
kernel.sched_min_granularity_ns = 10000000
kernel.sched_wakeup_granularity_ns = 15000000
kernel.sched_migration_cost_ns = 5000000
常见问题
- 上下文切换过高:减少线程数,使用 epoll 替代 select/poll
- 软中断过高:启用 RPS (Receive Packet Steering)
- CPU 节流:检查 cgroup 的 cpu.cfs_quota_us 限制
内存调优
监控命令
# 内存使用概览
free -h
cat /proc/meminfo
# 详细的进程内存
top -o %MEM
ps aux --sort=-%mem
# 内存映射
pmap -x <PID>
# Page Fault 统计
sar -B 1 # pgfault/s, pgmajfault/s
优化策略
# 1. 调整虚拟内存参数
# /etc/sysctl.d/99-memory.conf
vm.swappiness = 10 # 减少 swap 倾向
vm.dirty_ratio = 30 # 脏页比例
vm.dirty_background_ratio = 5
vm.vfs_cache_pressure = 50 # 缓存保留时间更长
# 2. 大页内存 (HugePages)
# 分配 1024 个 2MB 大页
echo 1024 > /proc/sys/vm/nr_hugepages
# 透明大页 (THP)
echo never > /sys/kernel/mm/transparent_hugepage/enabled
内存泄漏排查
# 1. 观察内存持续增长
pidstat -r 5 > mem.log
# 2. 分析堆内存
valgrind --tool=memcheck ./app
# 或使用 tcmalloc 的 HEAPPROFILE
# 3. 使用 /proc 分析
cat /proc/<PID>/smaps | grep -i pss | awk '{sum+=$2} END {print sum " kB"}'
磁盘 I/O 调优
监控命令
# I/O 统计
iostat -x 1 # 详细 I/O 信息
iotop # 按进程查看 I/O
# I/O 延迟
sar -d 1 # await, svctm, %util
# 注意:%util 100% 不一定代表饱和(现代 SSD)
# 文件系统缓存
cat /proc/meminfo | grep -E "(Dirty|Writeback)"
优化策略
# 1. I/O 调度器
# 检查当前调度器
cat /sys/block/sda/queue/scheduler
# 修改为适合 SSD 的 none 或 NVMe 的 mq-deadline
echo none > /sys/block/sda/queue/scheduler
# 2. 预读大小
blockdev --setra 4096 /dev/sda
# 3. 磁盘队列深度
echo 256 > /sys/block/sda/queue/nr_requests
# 4. 文件系统挂载选项
# SSD 建议使用 noatime, nodiratime
mount -o noatime,nodiratime,nobarrier /dev/sda1 /data
文件系统选择
| 文件系统 | 适用场景 | 特点 |
|---|---|---|
| ext4 | 通用 | 稳定,成熟 |
| XFS | 大文件,高并发 | 性能好,在线扩容 |
| Btrfs | 快照,压缩 | 功能丰富 |
| ZFS | 数据完整性 | 内存需求高 |
网络调优
监控命令
# 网络统计
sar -n DEV 1 # 网卡吞吐量
sar -n TCP,ETCP 1 # TCP 连接状态
netstat -s # 网络协议统计
# 连接队列
ss -lnt # 查看 Listen 队列
cat /proc/net/netstat | grep ListenOverflows
# 延迟
ping -c 100 <host> # 网络延迟
iperf3 -c <host> # 带宽测试
优化策略
# /etc/sysctl.d/99-network.conf
# TCP 缓冲区
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 131072 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
# 快速回收 TIME_WAIT
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
# 连接队列
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
# 端口范围
net.ipv4.ip_local_port_range = 1024 65535
性能基准测试
工具推荐
# CPU
sysbench cpu run
stress-ng --cpu 4 --timeout 60
# 内存
sysbench memory run
mbw -n 5 1024
# 磁盘
fio --name=test --ioengine=libaio --rw=randread --bs=4k --size=1G --numjobs=4
hdparm -Tt /dev/sda
# 网络
iperf3 -c <server> # 单线程
netperf -H <server> -l 60 # 多线程
系统调优检查清单
- CPU 运行队列是否合理(< CPU 核心数的 2 倍)?
- 是否存在大量上下文切换?
- 内存是否足够(不依赖 swap)?
- 磁盘 I/O 延迟是否在正常范围?
- 网络是否存在丢包或重传?
- 应用配置是否匹配硬件能力?
- 内核参数是否针对工作负载优化?
- 是否配置了合理的资源限制(cgroup)?
总结
系统性能调优是一个持续的观察-分析-优化循环。推荐从 Brendan Gregg 的 USE 方法入手,层层递进地排查瓶颈。每次优化只改变一个参数,并在修改前后收集数据对比,避免凭感觉调优。记住:先测量,再优化。