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 - 系统负载
uptime

2.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 MHz

2.3 上下文切换监控

# 查看上下文切换
vmstat 1

# 查看各进程上下文切换
pidstat -w 1

# 查看系统调用统计
strace -c -p <pid>

# 查看线程上下文切换
pidstat -t -w 1

2.4 中断监控

# 查看中断统计
cat /proc/interrupts

# 实时监控中断
watch -n 1 'cat /proc/interrupts'

# 查看软中断
cat /proc/softirqs

# 查看中断详情
mpstat -I SUM -P ALL 1

3. 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 ./myapp

3.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_us

3.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-info

4. 多核优化

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.svg

5.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

最佳实践

  1. 合理设置 CPU 亲和性:将关键进程绑定到特定核心,减少缓存失效。
taskset -pc 0-3 <pid>
  1. 使用性能模式:在需要高性能时设置为 performance 模式。
echo performance > /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
  1. 优化线程数:线程数不宜过多,通常设置为 CPU 核心数的 1-2 倍。

  2. 减少锁竞争:使用无锁数据结构、读写锁、减少锁的粒度。

  3. 使用缓存:减少重复计算,提高数据访问速度。

  4. 并行化处理:充分利用多核 CPU,提高吞吐量。

  5. 定期监控:使用监控工具持续跟踪 CPU 性能。

  6. 性能测试:优化前后进行性能测试,验证优化效果。

总结

本教程详细介绍了 Linux 系统 CPU 性能优化的方法和工具。通过实际案例,我们学习了如何识别 CPU 性能瓶颈、设置 CPU 亲和性、优化多核应用以及使用性能分析工具。掌握这些知识后,可以显著提升系统 CPU 利用率和应用性能。

« 上一篇 性能优化概述 下一篇 » 内存性能优化