如果想要提高 Linux 实例上托管的数据库或应用程序的性能。如何配置我的实例上的 HugePages 以提高性能?
Linux内存管理使用“分页机制”,内存页面默认大小为4KB。当运行内存需求量较大时,默认4KB大小的页面会导致较多的缺页中断,从而大大影响应用程序性能。
HugePages通过使用大页内存来取代传统的4KB内存页面,使得管理虚拟地址数变少,加快了从虚拟地址到物理地址的映射以及通过摒弃内存页面的换入换出以提高内存的整体性能。
在大型应用程序或数据库环境中的 Linux 实例内核中启用 HugePages,将有助于降低 TLB 上的压力。TLB 上的压力降低将可提升服务器和应用程序或数据库的性能,因为 TLB 只需存储较少尺寸更大的页面。
例如,如果 TLB 条目为 512 且在实例上未配置 HugePages,则内存大小约等于以下值:4096 B * 512 = 2 MB 内存大小。
如果 TLB 条目为 512 且在实例上配置了 HugePages,则内存大小约等于以下值:2 MB * 512 = 1 GB 内存大小。
下面步骤为在测试环境中配置 HugePages过程,在部署到生产环境之前,请自行测试其性能。
配置HugePages
1.查看您的内核当前是否启用 HugePages。
┌──(root@i-2udbbtytcx3gv6bvmhzb)-[/var/log]
└─# cat /proc/sys/vm/nr_hugepages
0
在上面的示例中,nr_hugepages 参数值为 0,表示 HugePages 未启用。
2.启用 HugePages,运行以下命令以将该内核参数值设置为 20。
┌──(root@i-2udbbtytcx3gv6bvmhzb)-[/var/log]
└─# sysctl -w vm.nr_hugepages=20
vm.nr_hugepages = 20
20为2MB大小的页面数。
3.验证系统在重新启动后分配 HugePages,请将以下条目添加到 /etc/sysctl.conf。
┌──(root@i-2udbbtytcx3gv6bvmhzb)-[/var/log]
└─# echo "vm.nr_hugepages=20" >> /etc/sysctl.conf
┌──(root@i-2udbbtytcx3gv6bvmhzb)-[/var/log]
└─# cat /etc/sysctl.conf | grep huge
vm.nr_hugepages=20
4.重新启动实例,然后,再次运行 cat 命令以验证 HugePages 值和配置。
┌──(root@i-2udbbtytcx3gv6bvmhzb)-[/var/log]
└─# cat /proc/sys/vm/nr_hugepages
20
5.检查 /proc/meminfo 中的可用 HugePages。
┌──(root@i-2udbbtytcx3gv6bvmhzb)-[/var/log]
└─# grep Huge /proc/meminfo
AnonHugePages: 253952 kB
ShmemHugePages: 0 kB
FileHugePages: 0 kB
HugePages_Total: 20
HugePages_Free: 20
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
-
HugePages_Total为所分配的页面数目,和Hugepagesize相乘后得到所分配的内存大小。
-
HugePages_Free为从来没有被使用过的Hugepages数目。例如即使已经分配了这部分内存,但是如果没有实际写入,那么看到的还是Free的。
-
HugePages_Rsvd为已经被分配预留但是还没有使用的page数目。
可以看到服务器上已启用了 HugePages,大小为2048KB,Total数量为20,Free为20。
禁用 HugePages 的方法:
- 将 nr_hugepages 改回 0。
- 删除 sysctl.conf 中的条目。
- 重新启动服务器以使其生效
测试HugePages使用
HugePages 的使用需要借助 Hugetlb文件系统,测试步骤如下:
1.挂载
┌──(root@i-2udbbtytcx3gv6bvmhzb)-[/var/log]
└─# mount -t hugetlbfs none /mnt/huge
┌──(root@i-2udbbtytcx3gv6bvmhzb)-[/mnt]
└─# mount | grep mnt
none on /mnt/huge type hugetlbfs (rw,relatime,pagesize=2M)
2.测试代码
#include <fcntl.h>
#include <sys/mman.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/unistd.h>
#define MAP_LENGTH (10*1024*1024) // 10MB
int main()
{
int fd;
void * addr;
/* 1. 创建一个 Hugetlb 文件系统的文件 */
fd = open("/mnt/huge/hugepage2", O_CREAT|O_RDWR);
if (fd < 0) {
perror("open()");
return -1;
}
/* 2. 把虚拟内存映射到 Hugetlb 文件系统的文件中 */
addr = mmap(0, MAP_LENGTH, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if (addr == MAP_FAILED) {
perror("mmap()");
close(fd);
unlink("/mnt/huge/hugepage1");
return -1;
}
strcpy(addr, "This is HugePages example...");
/* printf("%s\n", addr); */
printf("%p\n", addr);
printf("%s\n", addr);
/* 3. 使用完成后,解除映射关系 */
// munmap(addr, MAP_LENGTH);
// close(fd);
// unlink("/mnt/huge/hugepage1");
// printf("complete");
// return 0;
}
3.执行代码进行测试
执行代码之前查看hugepage信息:
┌──(root@i-2udbbtytcx3gv6bvmhzb)-[/mnt]
└─# grep Huge /proc/meminfo
AnonHugePages: 0 kB
ShmemHugePages: 0 kB
HugePages_Total: 20
HugePages_Free: 20
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
可以看到Total为20,Free为20 size为2048KB
- 执行一次代码后,查看hugepages信息:
┌──(root@i-2udbbtytcx3gv6bvmhzb)-[/mnt]
└─# grep Huge /proc/meminfo
AnonHugePages: 0 kB
ShmemHugePages: 0 kB
HugePages_Total: 20
HugePages_Free: 19
HugePages_Rsvd: 4
HugePages_Surp: 0
可以看到Free变为了19,Hugepage被使用
- 再执行一次,查看hugepages信息:
┌──(root@i-2udbbtytcx3gv6bvmhzb)-[/mnt]
└─# grep Huge /proc/meminfo
AnonHugePages: 0 kB
ShmemHugePages: 0 kB
HugePages_Total: 20
HugePages_Free: 18
HugePages_Rsvd: 8
HugePages_Surp: 0
Hugepagesize: 2048 kB
可以看到Free变为了18,Hugepage被使用
如果您有其他问题,欢迎您联系火山引擎技术支持服务