目录

Java大内存页支持

从Java SE 5.0开始设置了一个大内存页的开关-XX:+UseLargePage, 在Solaris平台默认打开,在Windows和Linux平台默认关闭。大内存支持的目的是为了优化处理器命中TLB的概率。

Translation-Lookside Buffer(TLB)是一个地址高速变换缓存。在内存分页的情况下,需要一个页表来缓存各个页表跟物理内存地址的对应关系。页表存放在内存中,所以需要访问内存时需要先到页表中进行查询,然后才能找到需要访问的地址。TLB是一个地址翻译缓存,保存了最近经常使用的虚地址翻译。TLB跟寄存器一样是系统的稀缺资源。处理器会根据虚地址现在TLB中查找,如果没有找到,称为一次TLB miss, 再向内存中页表查找,然后存入到TLB中。一次TLB miss会消耗很多的CPU时间,需要多次的内存访问。使用大页内存,一个TLB可以存储更大的内存范围的页地址对应关系。这对内存密集型应用性能提升有很大好处。

但是请注意在有的情况下大页内存可能反而会影响系统性能。例如,当一个应用占用很多的分页时,会造成内存的短缺,会产生swap等的分页使用,造成系统运行缓慢。同时需要注意如果系统运行很长时间,过多的碎片会造成大页内存申请失败。当出现这种情况的时候,OS或者JVM会选择使用常规分页。

启用大页内存需要的操作系统配置修改:

Solaris

从Solaris 9开始,使用Multiple Page Size Support(MPSS)技术,不需要其他另外的配置

Linux

大页内存需要内核版本2.6 以上支持。一些Linux厂商也在2.4的版本上提供了大页内存的支持补丁。为了确认系统是否支持大页内存,可以使用以下命令:

1
2
3
4
$ cat /proc/meminfo | grep Huge
HugePages_Total: 0
HugePages_Free: 0
Hugepagesize: 2048 kB

如果输出显示上面三个"Huge"变量,说明系统可以支持大页内存,但是需要进一步配置。如果上面的命令没有输出任何东西,说明不支持大页内存。配置使用大页内存必须使用root用户,需要的配置有:

  • 增大SHMMAX的值。必须使它大于Java堆内存的大小。在一个4GB内存的机器上下面的命令会使所有的内存可共享:echo 4294967295 > /proc/sys/kernel/shmmax

  • 设置大内存页数量。下面的例子中我们在一个4GB内存的系统中使用3GB做大内存页。假设一个大内存页的大小为2048K,所以3G=3 * 1024M = 3072M = 3072 * 1024K = 3145728K, 3145728K / 2048K = 1536, 所以:echo 1536 > /proc/sys/vm/nr_hugepages

注意/proc下面的配置值在系统重启后会重置,所以你可以将他们设置在rc.local或者sysctl.conf等启动脚本中

Windows

只有Windows Server 2003支持大页内存。为了使用它,必须使用administrator用户将相关权限赋给需要执行程序的用户

  • 选择 Control Panel 控制面板 - Administrative Tool 管理工具 - Local Security Policy 本地安全策略

  • 选择 Local Policies 本地策略 - User Rights Assignment 用户权限分配

  • 双击 “Lock pages in memory 锁定内存页面”,添加用户,用户组

  • 重启机器

注意上面的步骤就算是administrator用户执行程序也需要操作,因为administrator用户默认也没有锁定内存页面的权利。