CPU超分引发争用时,宿主机CPU利用率低但VM卡顿,核心是“资源可分配但不可及时调度”;需通过load average、vmstat的r/cs值、%st steal time等指标确认争用,并用virsh、ps、lscpu等定位源头及硬件瓶颈,再以降vCPU、CPU pinning、cgroups限频等方式精准缓解。

虚拟化环境下 CPU 超分(CPU overcommit)本身是常见设计,但一旦引发争用(contention),就会表现为宿主机 CPU 利用率不高、而客户机(VM)却严重卡顿或响应延迟——这是典型的“资源可分配但不可及时调度”问题。排查重点不在“谁吃了 CPU”,而在“谁在等 CPU”以及“调度是否公平”。
CPU 超分是否已实际引发争用?先看宿主机关键指标
登录宿主机后,不急着查 VM 进程,先确认争用是否存在:
- 看 load average 是否持续高于物理 vCPU 总数:比如 4 核宿主机,load > 4 持续 5 分钟以上,说明就绪队列积压,存在调度压力;但注意,若 load 高而 %us/%sy 很低、%id 接近 100%,则更可能是 I/O 等待导致的假性高负载,非 CPU 争用。
- 用 vmstat -w 1 观察 r(运行队列长度)和 cs(上下文切换):r 值长期 > 宿主机逻辑 CPU 数,且 cs 每秒超 2~3 万次,大概率是多 VM 抢占调度器时间片,内核频繁切换上下文。
- 检查 steal time(%st):在 top 或 vmstat 输出中找 %st 列(steal time)。该值代表 VM 等待宿主机 CPU 时间被其他 VM 占用的比例。若 %st > 5%,尤其在业务高峰期稳定维持,就是 CPU 超分争用的直接证据;> 20% 表明严重资源饥饿。
定位争用源头:哪些 VM 或 vCPU 在“抢”调度时间
宿主机上执行以下命令,聚焦虚拟化层视角:
Zynq‑7000 / Zynq UltraScale+ 硬件调试技能。适用于 Xilinx Zynq(Cortex‑A9/A53 + FPGA)Linux 环境,调试 I2C、I2S、UART、GPIO 等外设。包括设备树配置、内核驱动、用户空间调试工具、交叉编译和常见问题排查,支持 PetaLinux 开发。
-
查所有 QEMU/KVM 进程的 steal 时间:
ps -eo pid,comm,%cpu,%mem,pcpu,stime,etime,args --sort=-pcpu | grep qemu,结合/proc/[pid]/stat中第 38 字段(guest_steal_time)与第 39 字段(guest_stolen_time)可算出单个 VM 的 steal 占比。 -
用 virsh 查 VM 实时 vCPU 统计:
virsh vcpuinfo <vm-name>显示每个 vCPU 当前状态(running / idle / blocked)及运行时长;再配合virsh domstats <vm-name> | grep cpu.,重点关注cpu.time(总调度时间)、cpu.wait(等待调度时间)、cpu.stolen(被 steal 时间)。 -
识别“vCPU 密集型”VM:有些 VM 配置了远超其实际负载所需的 vCPU 数(如 16vCPU 但只跑单线程服务),会持续占用调度槽位。用
virsh list --all+virsh dumpxml <vm-name> | grep vcpu汇总各 VM 的 vCPU 分配量,对比其实际 %cpu 使用率(top -H -p $(pgrep -f "qemu.*<vm-name>")),若分配多、使用低,就是争用隐患点。
区分是调度争用,还是底层硬件瓶颈
避免误判的关键:确认问题出在虚拟化调度层,而非物理 CPU 或 NUMA 不匹配:
-
检查宿主机 CPU topology 和 NUMA 绑定:运行
lscpu和numactl --hardware。若 VM 分配了跨 NUMA 节点的 vCPU,而内存又未绑定到对应节点(virsh numatune <vm-name>),会导致远程内存访问延迟激增,表现类似 CPU 争用。 -
观察 per-CPU 使用是否严重不均:执行
mpstat -P ALL 1,看是否某些物理核心长期 95%+,而其余核心闲置。这往往说明 VM 的 vCPU 未做 CPU pinning,KVM 默认调度导致热点集中。 -
确认是否启用了 CPU 隔离(isolcpus)或实时调度策略:若有关键 VM 启用了
<cpu mode='host-passthrough'><numa>或设置了vcpupin,但宿主机未隔离对应 CPU,则争用会加剧。检查cat /proc/cmdline是否含isolcpus=,以及virsh vcpupin <vm-name>输出。
验证与缓解建议
确认争用后,优先从配置层面干预,而非临时 kill 进程:
- 对非关键 VM,降低 vCPU 数量,改用 CPU bandwidth 控制(cgroups v2):
virsh schedinfo <vm-name> --set cpu_quota=50000 --set cpu_period=100000(限制为 0.5 核)。 - 对高优先级 VM,启用 CPU pinning 并绑定到专用物理核心,同时关闭其 vCPU 的热插拔和自动迁移(
virsh setvcpus <vm-name> --maximum X --config+--vcpupin)。 - 检查宿主机 KVM 参数:确保
/sys/module/kvm/parameters/halt_poll_ns设置合理(默认 0,可设为 200000 减少空闲轮询开销),并确认kvm-intel.nested=1等参数未引入额外开销。

















