KVM半虚拟化设备virtio及性能调优佳实践

2020-06-01 00:00:00 内存 驱动 虚拟 性能 边界

为了提高硬盘,网络的性能,需要支持半虚拟化


在全虚拟化状态下,Guest OS不知道自己是虚拟机,于是像发送普通的IO一样发送数据,被Hypervisor拦截,转发给真正的硬件


在半虚拟化状态下,Guest需要安装半虚拟化驱动,Guest OS知道自己是虚拟机,所以数据直接发送给半虚拟化设备,经过特殊处理,发送给真正的硬件


半虚拟化驱动的例子:virtio, Vmware Tools



然而要虚拟的设备多种多样,要支持的硬件多种多样,需要统一的接口,这就是virtio的使命


不同的虚拟设备和不同的虚拟机可以有不同的前端驱动


不同的硬件设备可以有不同的后端驱动


两者之间的交互遵循virtio的标准


virtio层是虚拟队列接口,virtio-net网络驱动程序使用两个虚拟队列(一个用于接收,另一个用于发送),而virtio-blk块驱动程序仅使用一个虚拟队列。


Transport(virtio-ring)实现了环形缓冲区(ring buffer),用于保存前端驱动和后端处理程序执行的信息,并且它可以一次性保存前端驱动的多次I/O请求,并且交由后端去动去批量处理。





我们首先来看硬盘虚拟化virtio_blk


qemu-system-x86_64 -enable-kvm -name ubuntutest -m 2048 -balloon virtio -drive file=ubuntutest.qcow2,if=virtio -vnc :19 -net nic,model=virtio -net tap,ifname=tap0,script=no,downscript=n -monitor stdio


使用virtio_blk驱动的硬盘显示为/dev/vda,使用IDE硬盘显示为/dev/had,使用SATA硬盘显示/dev/sda


virtio-blk-data-plane:进一步提高性能,每个device单独的线程,仅支持raw disk,不支持storage migration



我们再来看网络设备虚拟化virtio_net


ethtool -i eth0


TSO是通过网络设备进行TCP段的分割,从而来提高网络性能的一种技术


GSO(Generic Segmentation Offload) 应用于其他的传输层协议,如TCPv6,UDP


应用层可以使用ethtool -K eth0 tso off|on命令对支持TSO特性的网络设备进行TSO功能的关闭和启用


使用virtio_net性能低,可尝试关闭这两个选项



使用Virtio的性能比较如下:


有了virtio性能会好很多。


所以性能优化的个佳实践是:使用半虚拟化驱动virtio,对于block storage,使用virtio_blk,对于network,使用virtio_net


在CPU方面


每个Guest相当于一个进程,Guest中的每个vcpu相当于一个线程


Host CPU支持进程间切换,SMP可以并行执行多个进程,从而可以进行CPU超配


CPU的超配增加了进程上下文切换,从而可能带来性能问题


为了保证Guest进行能够得到足够的时间片,常常使用cgroup的cpu.cfs_period_us和cpu.cfs_quota_us来控制


Cfs全称Completely Fair Scheduler是Linux Kernel的调度策略


cfs_period_us的意思是cgroup对CPU的调度的干预周期,cfs_quota_us是指则一个周期内这个进程得到的时间片长度。比如cfs_period_us=100000说明100毫秒cgroup进行一次干预,cfs_quota_us=25000表示在100毫秒里面,这个进程能够得到25毫秒的时间片,如果对cgroup进行的修改,则要等到下个100毫秒才起作用


Processor Pin: 可以讲vCPU pin到一个或者一组共享cache的物理CPU上,由于cache共享,则很多命令和数据都被缓存,从而提高性能。缺点是即便其他物理CPU空闲,由于绑定到了这个CPU,也得不到运行


CPU和Cache拓扑模型/sys/devices/system/cpu


virsh vcpupin guest# vproc# pproc#,pproc#




在内存方面


KSM全称Kernel Same Page Merging


Qemu向KSM注册内存,KSM对内存进行扫描,将相同的内存区域设为共享,并且copy on write


# cat /boot/config-3.13.0-27-generic | grep KSM CONFIG_KSM=y


共享内存节约内存空间,但是内存扫描同时影响性能


使用virtio_balloon


尽量不要使用swap,/proc/sys/vm/swappiness设为0


多核的两种方式:SMP和NUMA


SMP的问题主要在CPU和内存之间的通信延迟较大、通信带宽受限于系统总线带宽,同时总线带宽会成为整个系统的瓶颈


NUMA(Non-Uniform Memory Access):每个处理器有其可以直接访问其自身的“本地”内存池,使CPU和这块儿内存之间拥有更小的延迟和更大的带宽。而且整个内存仍然可做为一个整体,可以接受来自任何CPU的访问。


禁止zone_reclaim_mode:/proc/sys/vm/zone_reclaim_mode


当操作系统分配内存时,发现CPU本节点的内存已满,如果reclaim=true,则将会回收一部分本地内存,否则将分配其他节点的内存


使用KSM和Huge Page都会造成reclaim


建议开启大页Huge pages,从而提高地址转换的效率


普通页:PDPT -> PD -> Page Table -> In Page Offset


Translation Lookaside Buffer (TLB)是一个从虚拟地址到物理地址转换的一个Cache


Huge Page不但使得每次地址转换比较快,而且使得TLB每个记录较小,相同的内存的情况下,保存的记录较多,Cache命中率较高


大页:PDPT -> PD -> In Page Offset



在网络方面


使用tap作为网卡配置


使用virtio_net


使用PCI passthough可以提高性能,但是影响虚拟机迁移


可以使用DPDK或者SR-IOV




在存储方面


尽量使用block device,性能更好,无需管理HOST文件系统,无需管理稀疏文件,I/O Cache以4K为边界。


如果不能使用block device,则只好使用Image File。易管理,易移动,但需要HOST文件系统,需要管理稀疏文件


Partition问题:标准分区软件分区是以512byte一个Cylinder为边界的,Linux系统的I/O Cache是以4K为边界的,所以Linux下的标准文件系统将分区format的时候,会将文件以4k为边界进行存储,从而每次缓存正好缓存整个page(大小4k)


Image File作为一个文件,在Host文件系统中一定是以4k为边界的,然而一个Image File对于Guest来讲是整块硬盘,对其分区的时候往往不是以4K为边界的,从而Guest上读取文件的时候,本来是读取缓存的4K一个page,映射到Host文件系统上,变成了两个Page。写入也要更新两个页。



Host使用ext3文件系统,因为ext4的barrier会影响性能


使用raw image,比qcow2性能要好


选择正确的cache策略:


Page Cache: Host和Guest在FS和Block层都有自己的Page Cache,我们无法控制Guest里面的设置,但是可以配置Host Page Cache


Disk Write Cache在Hypervisor层


Cache Mode有以下四种,推荐使用none


I/O Scheduler推荐使用Deadline I/O scheduler





相关文章