Appearance
上下文切换指标 —— cswch/s、nvcswch/s、%wait
vmstat 1看到cs每秒钟几万,算不算高?pidstat -w里的cswch/s和nvcswch/s有什么区别?%wait是进程在等 CPU 的时间吗?本文厘清三类上下文切换指标的定义、触发条件和排查公式。与 iowait.md 的第 §一.5 节(两种上下文的统计窗口)互补阅读。
更新时间:2026-08-06
一、指标速览
| 指标 | 全称 | 含义 | 触发场景 | 来源工具 |
|---|---|---|---|---|
cs(系统级) | context switches | 全局每秒钟上下文切换总次数(含 voluntary + involuntary) | 所有类型均计入 | vmstat:cs、sar -w:cswch/s |
cswch/s(进程级) | voluntary context switches | 自愿上下文切换——进程主动放弃 CPU | 进入 S 态睡眠(网络 I/O、锁、sleep、epoll_wait) | pidstat -w、/proc/<pid>/status |
nvcswch/s(进程级) | involuntary context switches | 非自愿上下文切换——被内核强制抢走 CPU | 时间片耗尽、被更高优先级进程抢占 | pidstat -w、/proc/<pid>/status |
%wait(进程级) | % wait | 进程在就绪队列中排队等待 CPU 的时间占比 | R 态但不在 CPU 上执行 | pidstat -u、pidstat -w |
二、自愿上下文切换(cswch/s)——"我在等"
触发过程:
- 进程调用
read()/write()/sleep()/pthread_mutex_lock()等阻塞操作 - 内核将其状态从 R → S(可中断睡眠),让它离开运行队列
- 调度器选择下一个 R 态进程执行
- 这次放弃 CPU 的动作 → cswch/s +1
告诉你什么:
- cswch/s 高 = 进程频繁主动让出 CPU,大多数时间在等资源(I/O、锁、网络数据、定时器)
- cswch/s 是必要的开销——进程在等 I/O 时不应该占着 CPU
正常 vs 异常:
| cswch/s | 含义 | 排查方向 |
|---|---|---|
| < 1000 | 正常 | — |
| 1000-5000 | 频繁阻塞 | 检查是否可减少 syscall、使用批量 I/O |
| > 5000 | 极高,阻塞开销显著 | strace -c 统计系统调用频率,看哪个 syscall 占比最高 |
排查命令:
bash
pidstat -w 1 # 按进程显示 cswch/s 和 nvcswch/s
pidstat -wt 1 # 加 -t 按线程拆分(定位多线程场景的锁等待)
cat /proc/<pid>/status | grep ctxt # 进程生命周期累计值三、非自愿上下文切换(nvcswch/s)——"被抢了"
触发场景:
- 时间片耗尽:进程跑满了
sched_latency分配的时间片,调度器选择下一个进程 - 被抢占:更高优先级的进程(或实时进程)进入运行队列,当前进程被踢出
- 负载均衡:调度器在 CPU 之间迁移进程
告诉你什么:
- nvcswch/s 高 = CPU 不够用——进程在 CPU 上没跑够就被强制换下
- 这是纯 CPU 瓶颈指标,与 I/O 无关
判断公式:
通常的判断方法:
- 单核 nvcswch/s > 1000 → CPU 瓶颈
- 多核看 nvcswch/s 是否随 CPU 使用率同步增长排查命令:
bash
vmstat 1 # cs 列 = 全局 cswch + nvcswch,r 列 = 运行队列长度
# r > CPU 核数 → CPU 确实不够
pidstat -w 1 # 看哪个进程的 nvcswch/s 最高四、全局上下文切换(cs)——"系统有多忙"
vmstat 1 的 cs 列是整个系统每秒钟所有 CPU 核心上下文切换总和(包括 voluntary + involuntary + 内核线程 + 中断上下文)。
没有绝对的"正常值":
| 负载 | cs/s | 含义 |
|---|---|---|
| 轻负载 | < 1000 | 系统基本空闲 |
| 中负载 | 1000-10000 | 正常运行的应用 |
| 高负载 | 10000-50000 | 高并发网络服务(如单机 100K QPS) |
| 极高 | > 100000 | 可能是锁竞争风暴或系统调用密集 |
关键认知:上下文切换本身的开销约 1-5µs。但更致命的是切换带来的CPU 缓存污染——切换后 L1/L2 数据几乎全废,新进程需要重新建立缓存热度,间接开销远大于
cs数字字面上的时间。
五、%wait——进程在等 CPU 的时间
pidstat -u 输出中的 %wait 列:
$ pidstat -u 1
%usr %system %guest %wait %CPU CPU Command
20.0 5.0 0.0 30.0 25.0 0 myapp%wait 表示:进程处于 R 就绪态、在运行队列中排队等待 CPU 的时间占总时间的比例。
- %wait 高 = CPU 调度延迟大,进程想跑但被其他进程挡住
- 结合
nvcswch/s高 → CPU 瓶颈确认。排查方向:降负载、优化代码、加 CPU。
六、四类切换的综合判断

Fig 6.1:三类上下文切换状态的判断逻辑。一个直观记忆:cswch 高 = "我在等别人",nvcswch 高 = "别人在抢我"。
七、一句话总结
自愿上下文切换(cswch/s)是进程主动放弃 CPU(S 态阻塞),标志着 I/O 或锁等待瓶颈;非自愿上下文切换(nvcswch/s)是内核强制抢走 CPU(时间片耗尽/被抢占),标志着 CPU 不足;全局 cs 没有绝对标准值,需要结合 r 列(运行队列)和 %wait 判断——r > CPU 核数 + nvcswch/s 高 = CPU 瓶颈;cswch/s 高 + iodelay 高 = 磁盘瓶颈;cswch/s 高 + iodelay 正常 = 网络或锁等待瓶颈。