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。

练习
- 切换 performanceondemand 后,运行 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 1cs(上下文切换)指标。


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远程访问比例是否可接受
  • 中断与软中断分布是否均衡

练习题(综合)#

  1. 编写脚本:自动采集 mpstat/vmstat/perf 并输出到日志文件。
  2. 将同一应用在绑定CPU与不绑定CPU下运行5分钟,比较上下文切换差异。
  3. 尝试将 sched_min_granularity_ns 调整为默认值的一半,观察延迟变化并回滚。