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大页来说,可用的分配数目就更少了。

大页使用情况可以通过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启动时,加上上述命令即可。

参考文档

hugepage的优势与使用

Table of Contents