本文主要介绍 KVM 虚拟机 CPU 绑定在 Libvirt/CGroup 中的实现思路、常用查看与配置方式,并整理一份用 UnixBench 做性能对照时的历史跑分摘要。原稿以读书笔记与跑分日志为主,完整的“动态热绑定”生产编排流程仍有待补全。
Libvirt 对虚拟机资源限制多建立在 Linux CGroup 之上:CPU 集合、配额、磁盘与网络 IO 等都可通过 CGroup 控制器约束进程组。直接对 QEMU 进程写 CGroup 可以生效,日常更推荐通过 Libvirt XML / virsh 管理,便于与域生命周期一致。
背景说明
CPU 绑定(pinning)的常见目的:
- 降低跨 NUMA 节点访问,稳定时延
- 避免与宿主机关键中断/其他 VM 抢核
- 做性能对比实验时固定算力边界
绑定对象通常是 vCPU 线程与宿主机逻辑 CPU(有时还要区分 sibling / 隔离 CPU)。是否“动态”取决于是否在虚拟机运行中改 pin;Libvirt 支持运行时 vcpupin,但生产变更仍要评估缓存亲和与业务抖动。
环境信息
| 项目 | 说明 |
|---|---|
| 虚拟化 | KVM + Libvirt(版本待确认) |
| 基准工具 | UnixBench 5.1.x |
| 对照样本 | 笔记本 WSL2 环境 vs 机房 KVM 客户机(历史 2020-09 记录) |
具体宿主机型号、是否 CPU isolation(isolcpus 等)以现场为准。
核心概念
CGroup 与 Libvirt
CGroup 按层级对进程组做资源限制与记账。虚拟机的 QEMU 进程及其 vCPU 线程可被放入特定 cpuset,从而只在允许的 CPU 上调度。Libvirt 在域 XML 中暴露 cputune 等配置,并在启动/热更新时落到 CGroup。
查看 vCPU 与物理 CPU 对应关系
virsh vcpuinfo <domain>
输出中通常包含每个 vCPU 的编号、是否 online、以及当前 CPU Affinity。若尚未 pin,亲和可能覆盖较多逻辑 CPU;pin 成功后应收敛到目标集合。
也可查看:
virsh vcpupin <domain>
用于列出当前 pin 映射(无参数时)或设置映射(带 vCPU 号与 CPU 列表时,以 virsh help vcpupin 为准)。
配置方式
运行时 pin(示例)
将域 <domain> 的 vCPU 0 绑到宿主机 CPU 2(示例,勿照抄编号):
virsh vcpupin <domain> 0 2
virsh vcpuinfo <domain>
多 vCPU 时按拓扑逐个设置,或使用 XML 一次性声明。判断标准:vcpuinfo / vcpupin 显示的亲和与预期一致,且业务线程未再跑到未授权 CPU(可用 taskset/htop 在宿主机侧核对 QEMU 线程,具体 PID 因环境而异)。
域 XML 中的 cputune(示例)
<cputune>
<vcpupin vcpu='0' cpuset='2'/>
<vcpupin vcpu='1' cpuset='3'/>
<!-- 视需要添加 emulatorpin、iothreadpin、vcpusched 等 -->
</cputune>
修改持久化 XML 后,按是否热更新选择 virsh define + 重启域,或使用支持的 live 更新路径。错误的 cpuset(超范围、与 host 拓扑冲突)可能导致启动失败或性能反噬。
与 NUMA、emulator 线程
仅 pin vCPU 有时不够:emulator、iothread 仍可能漂到其它核。完整方案常同时配置 emulatorpin / iothreadpin,并与 numatune 对齐。本篇不做展开,按宿主机 numactl -H 与业务时延目标单独设计。
用 UnixBench 做对照
UnixBench 适合做同环境变更前后或粗粒度平台差异对照,不适合单独作为上线 SLA 依据。跑分受频率、睿频、后台负载、WSL 虚拟化层影响很大。
历史样本摘要
下列 Index Score 摘自原稿完整日志(UnixBench 5.1.3),仅作数量级参考:
| 环境(脱敏描述) | CPU 概要 | 并行度 | System Benchmarks Index Score |
|---|---|---|---|
| 笔记本 WSL2 + CentOS 8 用户态 | Ryzen 7 4800H,16 逻辑 CPU | 1 copy | 约 1830 |
| 同上 | 同上 | 16 copies | 约 8282 |
| 机房 KVM 客户机 | Xeon E5-2640 v2,客户机 8 vCPU | 1 copy | 约 1081~1097 |
| 同上 | 同上 | 8 copies | 约 4463~4502 |
说明:
- WSL2 与裸金属/KVM 不可直接横比绝对分,虚拟化路径与内核不同。
- 客户机两次 8 并行跑分接近,说明该负载下结果可重复性尚可。
- 原稿未给出“绑定前 vs 绑定后”同机对照;若要验证 pin 收益,应在同一 KVM 域、固定负载下改 pin 再跑,并记录
vcpupin状态。
跑分注意
# 在目标环境安装/编译 UnixBench 后执行(路径以现场为准)
./Run
- 跑分期间尽量静置宿主机与其它 VM
- 记录
virsh vcpupin、是否限频、是否同 NUMA - 保留完整 log 时注意脱敏主机名
验证结果
CPU 绑定是否生效,建议同时满足:
virsh vcpupin <domain>与 XML 一致virsh vcpuinfo <domain>中亲和正确- 业务或基准在变更前后有可解释的差异(无差异也要记录,避免假阳性)
注意事项
- 过度绑定可能导致某个物理核过热/过载,而其它核空闲;要结合监控看
%steal、CPU 利用率与尾时延。 - 宿主机更新内核、迁移 VM、改 CPU 拓扑后,原 cpuset 可能失效,需要重做。
- 原稿含大段 UnixBench 原文输出与书籍章节引用,本文已收敛为可维护摘要;动态编排(例如按负载自动改 pin)不在现有材料范围内,标为待后续补写。
- 不要从互联网或记忆编造具体
vcpuinfo表格输出;以本机命令为准。
参考资料
- Libvirt 域 XML:CPU tuning
- virsh 手册:vcpupin / vcpuinfo
- UnixBench
- Linux 内核 Documentation 中关于 cpuset / cgroup 的说明(按发行版内核版本查阅)