Qemu中Guest OS向Host传输数据的高性能通信方式有哪些
QEMU场景下Guest OS向宿主机的高性能数据传输方案
以下为排除已测试的vhost-vsock、MMIO callbacks方案外,可落地的高吞吐低延迟通信机制,按实际性能表现排序:
- ivshmem-plain共享内存直连方案
这是目前性能最高的Guest-Host通信方式。QEMU启动时通过ivshmem-plain设备给Guest预留一段连续的、和Host进程用户态地址空间直接映射的共享内存区,Guest通过PCI BAR空间直接寻址访问这段内存,全程无VM exit、无内存拷贝开销。数据传输时仅需在Guest写完数据后,通过自定义的轻量doorbell(比如基于PCI MSI或者单寄存器MMIO写)触发一次通知即可,不需要像MMIO callbacks方案那样每次数据访问都陷入Hypervisor,实际带宽可以跑到接近内存总线速率,传输延迟在百纳秒级。注意不要选用带默认doorbell逻辑的ivshmem-doorbell设备,自带的通知逻辑冗余开销较高,自行实现极简通知逻辑性能更好。 - vhost-user自定义零拷贝设备方案
如果不想从零实现共享内存的地址映射、生命周期管理逻辑,可以基于vhost-user协议实现自定义轻量传输设备:把设备后端跑在Host用户态,通过VHOST_USER_SET_MEM_TABLE接口直接获取Guest物理地址到Host虚拟地址的映射表,Guest侧复用标准virtio驱动框架,通过virtqueue传递数据所在的共享内存地址偏移即可,全程不需要拷贝数据内容,仅传递元数据。相比内核态的vhost-vsock方案,少了内核协议栈、套接字缓冲区的多次拷贝开销,带宽通常可以提升40%~80%,小数据包延迟也能降低一半以上,且不需要给Guest打侵入性内核补丁。 - virtiofs DAX模式文件类传输方案
如果传输场景以文件、块数据为主,直接开启virtiofs的DAX(Direct Access)模式即可。QEMU会把Host侧共享目录的内存窗口直接映射到Guest物理地址空间,Guest读写共享文件时直接操作映射后的共享内存,跳过Guest页缓存、Host页缓存的两次拷贝,也不需要走9pfs、virtio-blk的块协议栈,实际性能是普通9pfs的3~6倍,大文件传输带宽远高于vhost-vsock方案,部署成本极低,不需要自定义驱动。 - 自定义轻量hypercall通道方案
如果可以接受给QEMU和Guest内核打少量补丁,可以自定义专用的hypercall通信号:Guest需要传输数据时,把数据所在的Guest物理地址、数据长度作为参数传入hypercall,仅触发一次VM exit陷入Host,QEMU侧拿到地址后直接通过内存映射批量读取数据即可。相比MMIO callbacks方案每次MMIO访问都触发VM exit的问题,超大数据块传输时的VM exit开销可以忽略不计,小数据包延迟比MMIO方案低一个数量级。
通用性能调优注意点:所有方案要跑满性能,都需要关闭Host和Guest侧的KSM(内核同页合并)、关闭对应内存区域的swap权限,给QEMU预留1GB/2MB大页,同时把Guest vCPU、通信中断、Host处理进程绑定到同一物理NUMA节点,避免跨NUMA访问的额外开销。
内容的提问来源于stack exchange,提问作者Animesh Kumar Sinha
相关产品推荐
相关产品推荐

