huge page

 

[root@localhost ~]# free -g
total used free shared buff/cache available
Mem: 510 129 377 0 3 339
Swap: 0 0 0
[root@localhost ~]# cat /proc/meminfo | grep -i huge
AnonHugePages: 0 kB
ShmemHugePages: 0 kB
HugePages_Total: 256
HugePages_Free: 255
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 524288 kB

 

#include <sys/mman.h>
#include <stdio.h>
#include <memory.h>

int main(int argc, char *argv[]) {
  char *m;
  size_t s = (8UL * 1024 * 1024);

  m = mmap(NULL, s, PROT_READ | PROT_WRITE,
                    MAP_PRIVATE | MAP_ANONYMOUS | 0x40000 /*MAP_HUGETLB*/, -1, 0);
  if (m == MAP_FAILED) {
    perror("map mem");
    m = NULL;
    return 1;
  }

  memset(m, 0, s);

  printf("map_hugetlb ok, press ENTER to quit!\n");
  getchar();

  munmap(m, s);
  return 0;
}

 

[root@localhost ~]# cat /proc/meminfo  | grep -i huge
AnonHugePages:         0 kB
ShmemHugePages:        0 kB
HugePages_Total:     256
HugePages_Free:      254
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:     524288 kB
[root@localhost ~]# free -g
              total        used        free      shared  buff/cache   available
Mem:            510         129         377           0           3         339
Swap: 

 

 

[root@localhost ~]# ps -elf | grep map
0 S root     115112 114967  0  80   0 -  8231 wait_w 07:26 pts/0    00:00:00 ./map
0 S root     115141 115051  0  80   0 -  1729 pipe_w 07:26 pts/1    00:00:00 grep --color=auto map
[root@localhost ~]# cat /proc/115112/map
map_files/ maps       
[root@localhost ~]# cat /proc/115112/maps
00400000-00410000 r-xp 00000000 08:10 22155957                           /data1/dpdk-19.11/demo/huge/map
00410000-00420000 r--p 00000000 08:10 22155957                           /data1/dpdk-19.11/demo/huge/map
00420000-00430000 rw-p 00010000 08:10 22155957                           /data1/dpdk-19.11/demo/huge/map
400000000000-400020000000 rw-p 00000000 00:0f 293434                     /anon_hugepage (deleted)
ffff9c9e0000-ffff9c9f0000 rw-p 00000000 00:00 0 
ffff9c9f0000-ffff9cb60000 r-xp 00000000 08:03 247                        /usr/lib64/libc-2.17.so
ffff9cb60000-ffff9cb70000 r--p 00160000 08:03 247                        /usr/lib64/libc-2.17.so
ffff9cb70000-ffff9cb80000 rw-p 00170000 08:03 247                        /usr/lib64/libc-2.17.so
ffff9cb80000-ffff9cb90000 rw-p 00000000 00:00 0 
ffff9cb90000-ffff9cba0000 r--p 00000000 00:00 0                          [vvar]
ffff9cba0000-ffff9cbb0000 r-xp 00000000 00:00 0                          [vdso]
ffff9cbb0000-ffff9cbd0000 r-xp 00000000 08:03 240                        /usr/lib64/ld-2.17.so
ffff9cbd0000-ffff9cbe0000 r--p 00010000 08:03 240                        /usr/lib64/ld-2.17.so
ffff9cbe0000-ffff9cbf0000 rw-p 00020000 08:03 240                        /usr/lib64/ld-2.17.so
fffff7cf0000-fffff7d20000 rw-p 00000000 00:00 0                          [stack]
[root@localhost ~]# 

 

 

 

#include <sys/mman.h>
#include <stdio.h>
#include <memory.h>

int main(int argc, char *argv[]) {
  char *m;
  size_t s = (16UL * 1024 * 1024*1024); //改大

  m = mmap(NULL, s, PROT_READ | PROT_WRITE,
                    MAP_PRIVATE | MAP_ANONYMOUS | 0x40000 /*MAP_HUGETLB*/, -1, 0);
  if (m == MAP_FAILED) {
    perror("map mem");
    m = NULL;
    return 1;
  }

  memset(m, 0, s);

  printf("map_hugetlb ok, press ENTER to quit!\n");
  getchar();

  munmap(m, s);
  return 0;
}

 

 

[root@localhost ~]# ps -elf | grep map
0 S root     115761 114967 21  80   0 - 262183 wait_w 07:39 pts/0   00:00:01 ./map
0 S root     115769 115051  0  80   0 -  1729 pipe_w 07:39 pts/1    00:00:00 grep --color=auto map
[root@localhost ~]# cat /proc/meminfo  | grep -i huge
AnonHugePages:         0 kB
ShmemHugePages:        0 kB
HugePages_Total:     256
HugePages_Free:      223
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:     524288 kB
[root@localhost ~]# cat /proc/115761/maps
00400000-00410000 r-xp 00000000 08:10 22155957                           /data1/dpdk-19.11/demo/huge/map
00410000-00420000 r--p 00000000 08:10 22155957                           /data1/dpdk-19.11/demo/huge/map
00420000-00430000 rw-p 00010000 08:10 22155957                           /data1/dpdk-19.11/demo/huge/map
400000000000-400400000000 rw-p 00000000 00:0f 292814                     /anon_hugepage (deleted)
ffffb1060000-ffffb1070000 rw-p 00000000 00:00 0 
ffffb1070000-ffffb11e0000 r-xp 00000000 08:03 247                        /usr/lib64/libc-2.17.so
ffffb11e0000-ffffb11f0000 r--p 00160000 08:03 247                        /usr/lib64/libc-2.17.so
ffffb11f0000-ffffb1200000 rw-p 00170000 08:03 247                        /usr/lib64/libc-2.17.so
ffffb1200000-ffffb1210000 rw-p 00000000 00:00 0 
ffffb1210000-ffffb1220000 r--p 00000000 00:00 0                          [vvar]
ffffb1220000-ffffb1230000 r-xp 00000000 00:00 0                          [vdso]
ffffb1230000-ffffb1250000 r-xp 00000000 08:03 240                        /usr/lib64/ld-2.17.so
ffffb1250000-ffffb1260000 r--p 00010000 08:03 240                        /usr/lib64/ld-2.17.so
ffffb1260000-ffffb1270000 rw-p 00020000 08:03 240                        /usr/lib64/ld-2.17.so
ffffffc30000-ffffffc60000 rw-p 00000000 00:00 0                          [stack]
[root@localhost ~]# free -g
              total        used        free      shared  buff/cache   available
Mem:            510         129         377           0           3         339
Swap:             0           0           0
[root@localhost ~]# 

 

Linux中hugepage的使用方法

 

Linux中hugepage的使用方法#

Linux中使用hugepage有两种方法,分别是

  • hugetlb
  • transparent huge page (THP)

其中,hugetlb基于显式分配并保留的大页,而THP按需将内存转换成大页,无需提前保留,提供更加灵活、对系统其他部分影响更小的大页使用方式。

Hugetlb使用方法#

分配大页
  1. 默认size大页

    echo N > /proc/sys/vm/nr_hugepages将试图分配N个大页,页面大小是默认的(一般是2MB)。如果原来保留的页面个数大于N,那么将会释放多出来的页面。如果连续内存不够将保留页面数上升到N,则尽最大努力分配。

    cat /proc/sys/vm/nr_hugepages可以查看保留页面个数。

  2. 在指定的NUMA结点试图分配N个指定页面大小的hugepage,修改或读取文件:/sys/devices/system/node/node<node_id>/hugepages/hugepages-<page_size>/nr_hugepages

  3. NUMA结点无关的指定页面大小的hugepage:/sys/kernel/mm/hugepages/hugepages-1048576kB/。如果直接写该文件来提升页面个数,将重复依次在各个NUMA结点试图分配一个页面(node0, node1, node2, node3, ..., node0, node1, node2, node3, ...)直到满足或不可进一步分配,例如:

    1. 在每个node资源充足的情况下,将均匀分配页面到各个node。
    2. 若只有一个node可以分配大页,则大页全部分配到该node上。
    3. 若所有node可分配大页的内存总量之和仍不能满足N,则每个node尽最大努力分配大页。
使用大页

这里仅介绍mmap使用大页的方法。

在mmap的flag中添加MAP_HUGETLB和<MAP_HUGE>。其中,<MAP_HUGE>为((N & MAP_HUGE_MASK) << MAP_HUGE_SHIFT)MAP_HUGE_MASK == 0x3f == 0b111111MAP_HUGE_SHIFT == 26N为大页size的log2(来源:When MAP_HUGETLB is set bits [26:31] encode the log2 of the huge page size.)

实例:

Copy
void *myMalloc1GbPage(size_t size) {
  int flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_HUGETLB |
              ((30 & MAP_HUGE_MASK) << MAP_HUGE_SHIFT); // 2^30 == 1G
  int protection = PROT_READ | PROT_WRITE;
  return mmap(NULL, size, protection, flags, -1, 0);
}

void *myMalloc2MbPage(size_t size) {
  int flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_HUGETLB |
              ((21 & MAP_HUGE_MASK) << MAP_HUGE_SHIFT); // 2^21 == 2M
  int protection = PROT_READ | PROT_WRITE;
  return mmap(NULL, size, protection, flags, -1, 0);
}

Transparent Huge Page#

分配大页

不需要显式分配,只需要修改/sys/kernel/mm/transparent_hugepage/enabledmadvisealways即可开启THP。

使用大页

为了使用大页,可以使用posix_memalign(3)分配aligned内存。若为madvise模式,则需要在代码中使用madvise(ptr, size, MADV_HUGEPAGE) 来在指定区域开启大页。

实例:

Copy
void *myMalloc2MbTHP(size_t size) {
	void *ptr;
	int ret = posix_memalign(&ptr, 1 << 21, size);
    if (ret != 0) {
        // ERROR HANDLE
    }
	madvise(ptr, size, MADV_HUGEPAGE);
	return ptr;
}

madvise正如其名,仅提供“建议”,具体是否分配大页还要根据实际情况。如果THP被设置为always,那么是否madvise(MADV_HUGEPAGE)就不重要了。

hugetlb和THP的优劣#

THP目前仅支持2MB的大页,不支持1GB大页,因此若想使用1GB大页则只能使用hugetlb。(NV的技术人员已经实现了1GB THP,但还没有merge到linux kernel主流版本中)

THP支持swap,并在需要时先将大页拆分成小页以便swap。此外,THP会尽可能分配大页,并在无法分配大页时falllback到小页分配,整个过程完全透明,用户友好。hugetlb不支持swap。

hugetlb能够保证保留的大页仅用于hugepage使用,这种固定分配方式在不同场景下具有不同的优劣势,需要结合具体使用情况分析。

THP需要守护进程进行大页管理,但其开销很小,对性能影响微乎其微。hugetlb不需要守护进程。

posted on 2020-08-31 19:33  tycoon3  阅读(164)  评论(0编辑  收藏  举报

导航