KVM虚拟机使用大页内存
通过使用hugepage分配可以提高性能,因为需要更少的页,因此需要更少Translation Lookaside Buffers (TLB,高速传送缓存),使用TLB可以减少将虚拟页地址转换成物理页地址的时间。
如果没有hugepage,使用标准4K页大小的话,可能产生大量TLB miss,影响性能
有兴趣的可以了解下x86架构下的内存寻址。
实验环境
宿主机系统(host):CentOS Linux release 7.4.1708 (Core)
libvirt:3.2.0
qemu: 2.9.0
宿主机默认大页
默认情况下,系统大页是2M大页,可以通过命令查看:
[root@localhost ~]# cat /proc/meminfo
MemTotal: 131460440 kB
MemFree: 1056184 kB
MemAvailable: 107479720 kB
...
HardwareCorrupted: 0 kB
AnonHugePages: 15855616 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
DirectMap4k: 345984 kB
DirectMap2M: 19173376 kB
DirectMap1G: 116391936 kB
Hugepagesize表示当前系统的默认大页(2M),如果想修改默认大页规格,可以在系统grub启动项项中添加
vim /boot/grub2/grub.cfg
default_hugepagesz=1G
修改之后效果为:
[root@localhost ~]# cat /proc/meminfo
MemTotal: 131460440 kB
MemFree: 1056184 kB
MemAvailable: 107479720 kB
...
HardwareCorrupted: 0 kB
AnonHugePages: 15855616 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 1048576 kB
DirectMap4k: 345984 kB
DirectMap2M: 19173376 kB
DirectMap1G: 116391936 kB
宿主机分配大页
hugepage的分配应该在启动时完成,或者在系统启动之后尽可能的先分配好。系统在运行一段时间后产生的内存碎片比较多,分配大页需要连续的空闲内存地址,有可能满足不了大页需求。特别对于1G大页来说,可用的分配数目就更少了。
-
sysctl命令
sysctl -w vm.nr_hugepages=8 or sysctl vm.nr_hugepages=8
这个命令只能分配默认的大页数量。
如果想每次开机生效,可以修改配置文件,添加如下配置:
vim /etc/sysctl.conf vm.nr_hugepages = 8
-
echo命令
echo 8 > /sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages echo 4096 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
对于多numa,会平分到每个node上(如果每个node内存足够),当然也可以指定node分配大页(X表示node编号)。
echo 4096 > /sys/devices/system/node/nodeX/hugepages/hugepages-2048kB/nr_hugepages echo 8 > /sys/devices/system/node/nodeX/hugepages/hugepages-1048576kB/nr_hugepages
-
在启动项中添加
vim /boot/grub2/grub.cfg hugepagesz=1G hugepages=8 hugepagesz=2M hugepages=4096 default_hugepagesz=1G
大页使用情况可以通过cat /proc/meminfo(只能查看默认大页的使用情况)
[root@localhost ~]# cat /proc/meminfo
MemTotal: 131460440 kB
MemFree: 1056184 kB
MemAvailable: 107479720 kB
...
HardwareCorrupted: 0 kB
AnonHugePages: 15855616 kB
HugePages_Total: 8 (总量)
HugePages_Free: 4 (剩余)
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 1048576 kB
DirectMap4k: 345984 kB
DirectMap2M: 19173376 kB
DirectMap1G: 116391936 kB
或者查看echo命令对应的文件夹中的文件值
[root@localhost hugepages-1048576KB]# cat nr_hugepages (总量)
8
[root@localhost hugepages-1048576KB]# cat free_hugepages (剩余)
4
挂载hugetlbfs
大页分配以后要挂载hugetlbfs,应用程序才可以使用
默认情况下,系统会挂载hugetlbfs文件系统
[root@localhost ~]# mount |grep hugetlbfs
hugetlbfs on /dev/hugepages type hugetlbfs (rw,relatime)
这个挂载的是1G还是2M大页,取决于系统默认大页值。
默认值为2M大页场景下,如果要使用1G大页,则需要再次为1G大页挂载hugetlbfs
mkdir /dev/hugepages-1048576kB
mount -t hugetlbfs -o pagesize=2MB test_1G /dev/hugepages-1048576kB
如果开机启动挂载,则需要添加到:
vim /etc/fstab
test_1G /dev/hugepages-1048576kB hugetlbfs pagesize=1GB 0 0
默认值为1G大页场景下,如果要使用2M大页则与上述类似,pagesize=2M即可。
libvirt配置
libvirt在启动时会从mount中读取挂载的hugetlbfs,如果mount动作在libvirt服务启动之后,则必须重启libvirtd服务才能生效。
在xml中配置如下
<memoryBacking>
<hugepages/>
</memoryBacking>
上述配置系统会采用默认的大页配置,也可以指定相应的大页内存。
1G大页配置
<memoryBacking>
<hugepages>
<page size="1" unit="G"/>
</hugepages>
</memoryBacking>
2M大页配置
<memoryBacking>
<hugepages>
<page size="2" unit="M"/>
</hugepages>
</memoryBacking>
官网中还page选项中附带nodeset选项,像是绑定numa,但是这个并不是强制,numa绑定还是要靠numatune属性来完成。
创建后可以查看大页相关的使用情况,前文已经讲述,不再贴图。
qemu支持
创建大页虚拟机后,可以看到qemu命令中相关参数:
-m 4096 -mem-prealloc -mem-path /dev/hugepages/libvirt/qemu/test_vm
手动用qemu启动时,加上上述命令即可。
参考文档