4.6.5 优化策略与参数调优
优化策略与参数调优以“先定位、再干预、可回滚”为原则,围绕调度、亲和性、电源管理、NUMA与中断分布,辅以应用层并发策略。以下内容包含原理草图、安装与命令示例、常见排错与练习。
1. 调度策略与优先级调整(含示例)#
目标:降低关键进程被抢占概率,减少调度延迟。
命令与解释:
# 查看当前进程优先级与调度策略
ps -eo pid,comm,ni,cls,pri --sort=-pri | head
# 将进程优先级从0调为-5(更高优先级)
sudo renice -n -5 -p 12345
# 将关键进程设为实时调度(谨慎使用)
sudo chrt -f -p 90 12345
# -f: SCHED_FIFO, 90: 优先级(1-99),PID为12345
排错
- 若设置实时调度后系统卡顿:
- 立即降级优先级或恢复普通调度:
bash
sudo chrt -o -p 0 12345
# -o: SCHED_OTHER
- 若 renice 报权限不足:确保使用 sudo 或具备 CAP_SYS_NICE。
练习
1. 启动一个高CPU进程(yes > /dev/null),观察 top 中调度变化。
2. 对其 renice -n 10,记录 top 的 CPU 占比变化。
2. CPU亲和性与绑定(含示例)#
目标:减少跨核迁移、提高缓存命中率。
# 查看进程当前亲和性
taskset -p 12345
# 绑定进程到CPU 0和1
sudo taskset -cp 0,1 12345
# 启动时绑定
taskset -c 2-3 /usr/local/bin/myapp
IRQ亲和性示例(网卡中断绑定)
# 查看网卡中断号
grep -i eth0 /proc/interrupts
# 将中断号为48绑定到CPU0(十六进制掩码)
echo 1 | sudo tee /proc/irq/48/smp_affinity
排错
- 若绑定无效:检查 cgroup/cpuset 是否限制了 CPU。
- 若单核热点:适当增加中断分散或启用 irqbalance。
安装
# 安装taskset(通常在util-linux)
sudo yum install -y util-linux
# 或
sudo apt-get install -y util-linux
练习
- 将 Nginx worker 绑定到不同核并对比 perf stat 的上下文切换数。
3. CPU频率与电源管理(含示例)#
目标:稳定频率,降低延迟抖动。
# 安装cpupower工具
sudo yum install -y kernel-tools
# 或
sudo apt-get install -y linux-tools-common
# 查看当前频率策略
cpupower frequency-info
# 设置performance策略
sudo cpupower frequency-set -g performance
排错
- 若提示无此 governor:检查内核是否启用 cpufreq。
- 若频率仍波动:核查 BIOS 电源策略或 C-State。
练习
- 切换 performance 与 ondemand 后,运行 stress-ng 比较延迟。
4. NUMA优化(含示例)#
目标:减少跨节点内存访问。
# 安装numactl
sudo yum install -y numactl
# 或
sudo apt-get install -y numactl
# 查看NUMA拓扑
numactl --hardware
# 将应用绑定到node0 CPU与内存
numactl --cpunodebind=0 --membind=0 /usr/local/bin/myapp
观察与解释
numastat -p 12345
# 关注 "OtherNode" 计数,越低越好
排错
- 若内存不足:应用可能 OOM,需调整 --membind 或扩大可用内存节点。
练习
- 启动应用分别绑定与不绑定,比较 numastat 的远程访问比例。
5. 中断与软中断优化(含示例)#
目标:避免中断集中导致单核软中断爆高。
# 查看软中断
cat /proc/softirqs | head
# 启用RPS(示例:为rx-0队列设置CPU掩码0-3)
echo 0f | sudo tee /sys/class/net/eth0/queues/rx-0/rps_cpus
# 调整RPS flow entries
sudo sysctl -w net.core.rps_sock_flow_entries=32768
排错
- 若 rps_cpus 不存在:网卡驱动或内核不支持。
- 若软中断未下降:考虑增大网卡队列或启用 RSS。
练习
- 在高并发压测下观察 ksoftirqd 占比变化。
6. 内核参数与系统限制(含示例)#
目标:优化调度粒度,扩展并发上限。
# 调度参数调优(仅示例,需评估)
sudo sysctl -w kernel.sched_min_granularity_ns=15000000
sudo sysctl -w kernel.sched_wakeup_granularity_ns=20000000
# 临时调整进程文件句柄/线程数
ulimit -n 65535
ulimit -u 65535
持久化配置
# /etc/sysctl.d/99-cpu-tuning.conf
kernel.sched_min_granularity_ns=15000000
kernel.sched_wakeup_granularity_ns=20000000
排错
- 若调整后抖动加剧:回滚配置并重载 sysctl -p。
练习
- 对比调度参数前后 vmstat 1 的 cs(上下文切换)指标。
7. 应用层并发与线程模型(含示例)#
目标:减少过度线程导致的切换开销。
# Java应用查看线程数
ps -Lp 12345 | wc -l
# Go应用限制GOMAXPROCS(示例)
export GOMAXPROCS=4
./my-go-app
排错
- CPU高但吞吐低:排查锁竞争与GC线程数。
- 线程数过多:结合核心数与负载类型收敛线程池。
练习
- 将线程池从 2xCPU 调整为 1xCPU,比较延迟与CPU占用。
8. 典型调优流程示例(可回滚)#
# 1) 基线采集
mpstat -P ALL 1 5
vmstat 1 5
perf top -g
# 2) 小步调整(示例:绑定CPU)
taskset -cp 0,1 12345
# 3) 验证变化
mpstat -P ALL 1 5
perf stat -p 12345 sleep 5
# 4) 回滚
taskset -cp 0-3 12345
9. 常见故障与恢复#
- 现象:实时调度导致系统失去响应
处理:进入单用户模式或通过chrt -o -p恢复普通调度。 - 现象:绑定后性能下降
处理:检查线程跨NUMA、IRQ单核热点,适当放宽CPU绑定范围。
10. 小结与检查清单#
- 调度策略是否与业务优先级匹配
- 亲和性是否导致单核热点
- 频率与电源策略是否与低延迟目标一致
- NUMA远程访问比例是否可接受
- 中断与软中断分布是否均衡
练习题(综合)#
- 编写脚本:自动采集
mpstat/vmstat/perf并输出到日志文件。 - 将同一应用在绑定CPU与不绑定CPU下运行5分钟,比较上下文切换差异。
- 尝试将
sched_min_granularity_ns调整为默认值的一半,观察延迟变化并回滚。