CPU 性能优化
核心知识点
1. CPU 性能基础
1.1 CPU 性能指标
┌─────────────────────────────────────────────────────┐
│ CPU 性能指标 │
├─────────────────────────────────────────────────────┤
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ CPU 使用率│ │ 上下文切换│ │ 中断次数 │ │
│ │ │ │ │ │ │ │
│ │ user │ │ voluntary│ │ hard │ │
│ │ system │ │ non-vol │ │ soft │ │
│ │ idle │ │ │ │ │ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ 运行队列 │ │ 负载平均 │ │ CPU 亲和性│ │
│ │ │ │ │ │ │ │
│ │ 长度 │ │ 1min │ │ 绑定 │ │
│ │ 等待时间│ │ 5min │ │ 优先级 │ │
│ │ │ │ 15min │ │ │ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ │
└─────────────────────────────────────────────────────┘1.2 CPU 性能瓶颈
| 瓶颈类型 | 表现 | 原因 |
|---|---|---|
| 高 CPU 使用率 | CPU 使用率持续 > 80% | 计算密集型应用、算法效率低 |
| 频繁上下文切换 | 上下文切换次数高 | 线程/进程过多、锁竞争 |
| 高中断率 | 中断次数异常高 | 网络流量大、硬件问题 |
| 运行队列过长 | 负载平均高 | CPU 资源不足、进程数多 |
| 单核瓶颈 | 单核使用率高 | 单线程应用、未利用多核 |
2. CPU 监控工具
2.1 基础监控工具
# top - 实时监控进程
top
# htop - 交互式进程监控
htop
# vmstat - 系统性能统计
vmstat 1
# mpstat - CPU 统计信息
mpstat -P ALL 1
# uptime - 系统负载
uptime2.2 CPU 使用率分析
# 查看 CPU 使用率
top
# 按 1 键显示每个 CPU 核心的使用率
# 查看各进程 CPU 使用率
ps aux --sort=-%cpu | head -20
# 查看系统 CPU 使用率
mpstat 1 10
# 查看详细 CPU 信息
cat /proc/cpuinfo
# 查看 CPU 频率
cat /proc/cpuinfo | grep MHz2.3 上下文切换监控
# 查看上下文切换
vmstat 1
# 查看各进程上下文切换
pidstat -w 1
# 查看系统调用统计
strace -c -p <pid>
# 查看线程上下文切换
pidstat -t -w 12.4 中断监控
# 查看中断统计
cat /proc/interrupts
# 实时监控中断
watch -n 1 'cat /proc/interrupts'
# 查看软中断
cat /proc/softirqs
# 查看中断详情
mpstat -I SUM -P ALL 13. CPU 性能优化方法
3.1 CPU 亲和性设置
CPU 亲和性可以将进程绑定到特定的 CPU 核心,减少缓存失效和上下文切换。
# 查看进程 CPU 亲和性
taskset -p <pid>
# 设置进程 CPU 亲和性(绑定到 CPU 0-3)
taskset -pc 0-3 <pid>
# 启动时设置 CPU 亲和性
taskset -c 0-3 ./myapp
# 查看线程 CPU 亲和性
ps -eo pid,tid,psr,comm | grep <pid>
# 使用 numactl 设置 NUMA 亲和性
numactl --cpunodebind=0 --membind=0 ./myapp3.2 进程优先级调整
# 查看进程优先级
ps -eo pid,ni,pri,comm | grep <pid>
# 调整进程优先级(nice 值范围 -20 到 19)
renice -n 5 -p <pid>
# 启动时设置优先级
nice -n 5 ./myapp
# 实时优先级(需要 root 权限)
chrt -f 50 ./myapp
# 查看实时优先级
chrt -p <pid>3.3 CPU 调度器优化
# 查看当前调度器
cat /sys/block/sda/queue/scheduler
# 设置调度器为 deadline
echo deadline > /sys/block/sda/queue/scheduler
# 设置调度器为 noop(SSD 推荐)
echo noop > /sys/block/sda/queue/scheduler
# 调整 CFS 调度器参数
echo 1000000 > /proc/sys/kernel/sched_rt_period_us
echo 950000 > /proc/sys/kernel/sched_rt_runtime_us3.4 CPU 频率调节
# 查看 CPU 频率调节器
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
# 查看可用的调节器
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors
# 设置为性能模式
echo performance > /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
# 设置为节能模式
echo powersave > /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
# 使用 cpupower 工具
cpupower frequency-set -g performance
cpupower frequency-info4. 多核优化
4.1 多线程编程
#include <pthread.h>
#include <stdio.h>
#define NUM_THREADS 4
void* thread_function(void* arg) {
int thread_id = *(int*)arg;
printf("Thread %d running on CPU %d\n",
thread_id, sched_getcpu());
return NULL;
}
int main() {
pthread_t threads[NUM_THREADS];
int thread_ids[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; i++) {
thread_ids[i] = i;
pthread_create(&threads[i], NULL,
thread_function, &thread_ids[i]);
}
for (int i = 0; i < NUM_THREADS; i++) {
pthread_join(threads[i], NULL);
}
return 0;
}4.2 进程池优化
import multiprocessing
import time
def worker(task_id):
print(f"Worker {task_id} running on CPU {multiprocessing.current_process()._identity}")
time.sleep(1)
return task_id * 2
if __name__ == "__main__":
num_processes = multiprocessing.cpu_count()
print(f"Number of CPU cores: {num_processes}")
with multiprocessing.Pool(processes=num_processes) as pool:
results = pool.map(worker, range(10))
print(f"Results: {results}")4.3 任务并行化
# 使用 xargs 并行执行
find . -name "*.log" | xargs -P 4 -I {} gzip {}
# 使用 GNU parallel 并行执行
ls *.log | parallel -j 4 gzip {}
# 使用 make 并行编译
make -j$(nproc)5. CPU 性能分析工具
5.1 perf 工具
# 实时性能分析
perf top
# 记录性能数据
perf record -g -p <pid>
# 生成性能报告
perf report
# 统计系统调用
perf stat -e syscalls:sys_enter_open -p <pid>
# 分析缓存命中率
perf stat -e cache-references,cache-misses ./myapp
# 生成火焰图
perf script | stackcollapse-perf.pl | flamegraph.pl > flamegraph.svg5.2 strace 工具
# 跟踪系统调用
strace -p <pid>
# 统计系统调用
strace -c -p <pid>
# 跟踪特定系统调用
strace -e trace=open,read,write -p <pid>
# 跟踪子进程
strace -f -p <pid>
# 显示时间戳
strace -T -p <pid>5.3 pstack 工具
# 查看进程堆栈
pstack <pid>
# 持续查看堆栈
watch -n 1 "pstack <pid>"
# 查看线程堆栈
ps -eLf | grep <pid>
pstack <tid>实用案例分析
案例 1:优化高 CPU 使用率应用
场景描述
一个数据处理应用 CPU 使用率持续在 90% 以上,需要进行优化。
操作步骤
# 1. 识别高 CPU 使用进程
top
ps aux --sort=-%cpu | head -20
# 2. 分析进程详情
pidstat -p <pid> 1 10
strace -c -p <pid>
# 3. 性能分析
perf top -p <pid>
perf record -g -p <pid>
perf report
# 4. 优化代码
# - 减少不必要的计算
# - 使用更高效的算法
# - 避免重复计算
# 5. 使用缓存
# - 添加内存缓存
# - 使用 Redis 缓存
# 6. 并行化处理
# - 使用多线程
# - 使用多进程
# 7. 验证优化效果
top
perf stat ./myapp
# 8. 持续监控
pidstat -p <pid> 1案例 2:减少上下文切换
场景描述
系统上下文切换频繁,导致性能下降。
操作步骤
# 1. 监控上下文切换
vmstat 1
pidstat -w 1
# 2. 识别高上下文切换进程
pidstat -w 1 | sort -k5 -n
# 3. 分析进程线程数
ps -eLf | grep <pid> | wc -l
# 4. 优化线程数
# - 减少线程池大小
# - 使用协程替代线程
# 5. 设置 CPU 亲和性
taskset -pc 0-3 <pid>
# 6. 优化锁竞争
# - 减少锁的粒度
# - 使用无锁数据结构
# - 使用读写锁
# 7. 使用进程替代线程
# - 减少上下文切换
# - 提高隔离性
# 8. 验证优化效果
vmstat 1
pidstat -w 1案例 3:多核应用优化
场景描述
一个单线程应用未充分利用多核 CPU。
操作步骤
# 1. 查看 CPU 核心数
nproc
cat /proc/cpuinfo | grep processor | wc -l
# 2. 分析应用 CPU 使用
top
# 按 1 键查看各核心使用率
# 3. 识别单线程瓶颈
perf top -p <pid>
# 4. 多线程改造
# - 将任务分解为独立单元
# - 使用线程池
# - 避免共享状态
# 5. 多进程改造
# - 使用进程池
# - 使用消息队列通信
# 6. 设置 CPU 亲和性
taskset -pc 0-3 <pid>
# 7. 调整调度策略
chrt -f 50 ./myapp
# 8. 验证优化效果
top
mpstat -P ALL 1最佳实践
- 合理设置 CPU 亲和性:将关键进程绑定到特定核心,减少缓存失效。
taskset -pc 0-3 <pid>- 使用性能模式:在需要高性能时设置为 performance 模式。
echo performance > /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor优化线程数:线程数不宜过多,通常设置为 CPU 核心数的 1-2 倍。
减少锁竞争:使用无锁数据结构、读写锁、减少锁的粒度。
使用缓存:减少重复计算,提高数据访问速度。
并行化处理:充分利用多核 CPU,提高吞吐量。
定期监控:使用监控工具持续跟踪 CPU 性能。
性能测试:优化前后进行性能测试,验证优化效果。
总结
本教程详细介绍了 Linux 系统 CPU 性能优化的方法和工具。通过实际案例,我们学习了如何识别 CPU 性能瓶颈、设置 CPU 亲和性、优化多核应用以及使用性能分析工具。掌握这些知识后,可以显著提升系统 CPU 利用率和应用性能。