为何使用巨页?html
当一个进程使用一些内存的时候,CPU就把那部份内存标记成已被该进程使用的。为了提升效率,CPU会按4K字节块(它在不少平台上是默认值)分配内存。这些块被称做页。这些页能够被交换到磁盘上,等等。java
由于进程地址空间是虚拟的,CPU和操做系统就得记住哪一页属于哪一个进程,存储在什么地方。显然的,拥有的页面越多,就得花费越多的时间去寻找那些内存被映射的地方。若是一个进程使用了1GB的内存,就得查找262144(1GB/4K)个条目。若是一个页表条目占用8字节,那么就得查找2MB(262144*8)。node
当前大多数CPU体系结构支持更大的页(这样CPU/OS要查找的条目就少了),这些页在Linux上被称做巨页(Huge pages),在BSD上被称做超级页(Super Pages),在Windows上被称做大页(Large Pages),它们都是一样的东西。mysql
目录linux
想知道更多关于hugetlbpage的信息,请阅读这篇文档。sql
目前,没有标准的方式来启用HugeTlbfs,主要由于FHS(文件系统构架标准)中没有这种虚拟文件系统的相关规定。参见572733。(Fedora把它挂载在/dev/hugepages上了,因此若是你在网上看到一些使用这个位置的例子,就不要惊讶了)数据库
Debian是从DebianLenny(其实是从2.6.23)开始支持“巨页表”(HugeTlb)的。在ibm.com上能够找到详细的大页介绍。缓存
% groupadd my-hugetlbfs % getent group my-hugetlbfs my-hugetlbfs:x:2021: % adduser franklin my-hugetlbfs Adding user `franklin' to group `my-hugetlbfs' ... Adding user franklin to group my-hugetlbfs Done.
# Allocate 256*2MiB for HugePageTables (YMMV) vm.nr_hugepages = 256 # Members of group my-hugetlbfs(2021) can allocate "huge" Shared memory segment vm.hugetlb_shm_group = 2021
% mkdir /hugepages
hugetlbfs /hugepages hugetlbfs mode=1770,gid=2021 0 0
你应该配置一个用户能够锁定的内存数量,这样一个应用程序就不会经过锁定全部内存而致使操做系统崩溃。注意并非只有巨页能够能够被锁定,内存中的任何页面均可以被锁定。你应该容许进程锁定多一点的内存(只是巨页空间)。架构
## Get huge-page size: % grep "Hugepagesize:" /proc/meminfo Hugepagesize: 4096 kB ## What's the current limit % ulimit -H -l 64 ## Just add them up... (how many pages do you want to allocate?)
参见Limits(ulimit -l 和/etc/security/limits.conf中的memlock)。less
某些架构(如ia64)能够有多倍的和(或)可配置的(巨)页尺寸。
(TODO)
参见:
Debian arm64 内核(用4KB标准PAGE_SIZE运行)支持2MB和1GB的 HugeTLB 页大小。一种是在内核命令行上指定参数,从而使启动时预分配1GB的 HugeTLB 页面。下面的文本将预分配10*1GB的巨页。
hugepagesz=1G hugepages=10
若是某人决定用 CONFIG_ARM64_64K_PAGES=y 来构建他本身的 Debian arm64 内核,那么只可使用512MB的 HugeTLB(和THP)页面。这些在运行时可用。
依据处理器,在 x86_64 架构上至少有两种不一样的巨页尺寸:2MB和1GB。若是CPU支持2MB页面,它会在cpuinfo中有 PSE 旗标;若是支持1GB页面,它就会有 PDPE1GB 旗标。/proc/cpuinfo 显示了是否设置了这两种旗标。
若是下面这个命令返回非空字符串,就支持2MB页面。
% grep pse /proc/cpuinfo | uniq flags : [...] pse [...]
若是下面这个命令返回非空字符串,就支持1GB页面。
% grep pdpe1gb /proc/cpuinfo | uniq flags : [...] pdpe1gb [...]
若是想要两者均可用,那么可能须要在启动时激活它们。下面的内核启动参数启用1GB页面而且建立了一个1GB页面池。
hugepagesz=1GB hugepages=1
在启动后,巨页池看起来像下面这样:
% hugeadm --pool-list Size Minimum Current Maximum Default 2097152 0 0 0 * 1073741824 1 1 1
你能够用hugeadm获取到一张可用巨页尺寸列表:
% hugeadm --page-sizes-all 2097152 1073741824
hugeadm也显示每一个可用尺寸的已分配数量:
% hugeadm --pool-list Size Minimum Current Maximum Default 2097152 0 0 0 * 1073741824 1 1 1
另外一种获取默认巨页尺寸的当前可用/已用页的方法是查看/proc/meminfo:
% grep Huge /proc/meminfo HugePages_Total: 256 HugePages_Free: 256 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 4096 kB
(想了解关于巨页的更多信息,请阅读文献/vm/hugetlbpage.txt)
标准Debian内核启用了HUGETLB(Lenny呢?Xen呢?):
% grep HUGETLB /boot/config-$(uname -r) CONFIG_HUGETLBFS=y CONFIG_HUGETLB_PAGE=y
各类运行时设置(参见文献资料)。
% grep -R "" /sys/kernel/mm/hugepages/ /proc/sys/vm/*huge* /sys/kernel/mm/hugepages/hugepages-4096kB/nr_hugepages:256 /sys/kernel/mm/hugepages/hugepages-4096kB/nr_overcommit_hugepages:0 /sys/kernel/mm/hugepages/hugepages-4096kB/free_hugepages:256 /sys/kernel/mm/hugepages/hugepages-4096kB/resv_hugepages:0 /sys/kernel/mm/hugepages/hugepages-4096kB/surplus_hugepages:0 /proc/sys/vm/hugepages_treat_as_movable:0 /proc/sys/vm/hugetlb_shm_group:0 /proc/sys/vm/nr_hugepages:256 /proc/sys/vm/nr_overcommit_hugepages:0
体系架构 |
巨页尺寸 |
arm64 | 4K, 2M, 1G(或者64K和512M,若是用CONFIG_ARM64_64K_PAGES=y构建本身的内核的话) |
i386 | 4M, 4M(在PAE模式下是2M) |
ia64 | 4K, 8K, 64K, 256K, 1M, 4M, 16M, 256M |
ppc64 | 4K, 16M |
libhugetlbfs库提供了简单的访问巨页内存的方式。它还包含一些用户空间工具来提高巨页的易用性,进行环境设置和控制等。
http://libhugetlbfs.ozlabs.org/
533708 - ITP: libhugetlbfs -- Initial package request
http://www.ibm.com/developerworks/wikis/display/LinuxP/libhuge+short+and+simple
PostgreSQL的HugeTLB(和其余应用)非正式
http://oss.linbit.com/hugetlb/
一个应用程序能够经过两种不一样的方式分配/使用HugeTlbPage:
应用程序 |
hugetlbfs |
共享内存 |
QEMU/KVM | 是 | 否 |
MySQL | 否 | 是 |
Java | 否 | 是 |
(TODO),参见:
Linux HugeTLBfs:提高MySQL数据库应用程序性能
http://www.cyberciti.biz/tips/linux-hugetlbfs-and-mysql-performance.html (未测试)
Sun和OpenJDK可使用大页。
(TODO)
总的来讲,要启用巨页,彷佛得使用 -XX:+UseLargePages 选项运行java。Java堆(-Xmx)的上限尺寸应该能够容纳你预留的巨页;使用 ulimit -l 和/或 /etc/security/limits.conf 中的memlock。
参见:
可能的错误:
% java -XX:+UseLargePages Java HotSpot(TM) Server VM warning: Failed to reserve shared memory (errno = 1). Java HotSpot(TM) Server VM warning: Failed to reserve shared memory (errno = 22).
memcached可以使用巨页,请阅读手册页:
尝试使用大内存页(若是可用)。增长内存页尺寸能够减小TLB漏掉的数量,并提高性能。为了从操做系统里获取大页,memcached将会把全部的条目缓存分配到一个大页块中。只有你的操做系统支持大页的时候才可用。
PostgreSQL 从版本9.4开始支持巨页。关于以前的版本,参见上面的hugetlblib。
巨页虚拟化的一些建议:
(TODO),参见:
(TODO)
Xen从哪一个版本开始支持巨页,还有它如何使用,都不是很清楚。
说明:本文译自https://wiki.debian.org/Hugepages。因为英语水平有限,语句不通顺处还请谅解。