0%

为 Java 启用大页面支持

为 Java 启用大页面支持

Oracle G1GC Tuning中提到,使用大页面可以提高吞吐量,在这里记录一下Linux服务器的开启方式

本文基于Ubuntu 18.04 LTSOpenJDK 11.0.4编写,不同版本操作可能稍有不同

为操作系统启用大页面

准备工作

执行cat /proc/meminfo | grep -i HugePages,如果有类似如下输出,则表示服务器支持大页面:

1
2
3
4
5
6
7
AnonHugePages:   1013760 kB
ShmemHugePages: 0 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB

可以看到,大页面每个页面的大小为2048 kB

你需要根据具体需求来计算你需要多少大页面,如你应用的堆为4GB,按照上面2048 kB的大页面大小,你一共需要4 * 1024 * 1024 / 2048 = 2048个大页面

如果你希望元空间也使用大页面,则也需要一并计算在内,如你的元空间占用200MB,则建议预留200 * 1024 / 2048 = 100个大页面,两者加起来一共需要2148个大页面

为了避免出现大页分配失败的警告,建议在实际需要的页面数上再额外加一些,如64个页面,那么对于上述例子,我们一共需要2212个大页面,共占用4424MB

启用大页面

需要注意的是,大页面即使未使用,也会一直占用你的内存,因此,你可能需要先停止正在运行的服务来提供充足的内存空间

执行echo <页面数> > /proc/sys/vm/nr_hugepages来生成大页面,如上面的例子,我们应该执行echo 2212 > /proc/sys/vm/nr_hugepages

执行完毕后,可以再次执行cat /proc/meminfo | grep -i HugePages来查看申请的大页面:

1
2
3
4
5
6
7
AnonHugePages:   1013760 kB
ShmemHugePages: 0 kB
HugePages_Total: 2212 <--- 这就是申请到的大页面数量
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB

如果你发现申请到的大页面数量和你预期的不符,则可能是因为系统剩余内存不足,这时建议先关闭正在运行的应用,释放充足的内存后重新生成大页面

开机自动设置

上面启用大页面的方法在重启后就会失效,重启后你会发现大页面数又重新变回了0

因此我们需要设置一个脚本来在开机时自动生成大页面:

  1. 新建一个启用大页面的脚本,如我放在了/root/shells/hugepages:

    1
    2
    3
    4
    5
    6
    7
    8
    #!/bin/sh

    ### BEGIN INIT INFO
    # Provides: hugepages
    # Default-Start: 2 3 4 5
    ### END INIT INFO

    echo 2176 > /proc/sys/vm/nr_hugepages
  2. 设置这个脚本开机自启动

    1
    2
    3
    cd /etc/init.d
    ln -s /root/shells/hugepages hugepages
    update-rc.d hugepages defaults

这样,下次重启后就会自动生成大页面了

ulimit

根据Oracle HugePages说明,应该将ulimit中的memlock增加到至少为内存大小的90%,这个数字是以kB为单位的

例如,对于64GB内存的机器,这个值应该为64 * 1024 * 1024 * 0.9 = 60397977.6,去掉小数为60397977

接着,在/etc/security/limits.conf中添加下面两行即可:

1
2
*   soft   memlock    60397977
* hard memlock 60397977

在运行你的应用之前,你应该先退出当前Shell并重新登陆来使修改生效

特别的,对于用root用户运行的应用,上述设置是无效的,应在/etc/security/limits.conf中添加下面两行:

1
2
root   soft   memlock    60397977
root hard memlock 60397977

禁用大页面

如果你不再需要使用大页面了,可以先关闭所有使用大页面的应用,然后执行echo 0 > /proc/sys/vm/nr_hugepages来删除所有大页面

如果你使用了开机自动设置大页面,则可执行update-rc.d hugepages remove来取消自动设置

为 Java 应用设置大页面

在你的启动参数中增加-XX:+UseLargePages即可启用大页面,如果你还想为元空间启用大页面,则需要增加XX:+UseLargePagesInMetaspace

对于内存占用较大的应用,启用大页面后你会观察到它的内存占用量大幅下降,这是正常的,因为通过大页面占用的内存是不统计在进程的res中的

如果你看到类似下面这种警告:

1
Java HotSpot(TM) 64-Bit Server VM warning: Failed to reserve large pages memory req_addr: 0x0000000000000000 bytes: 8388608 (errno = 12).

这说明你的大页面数量不足,你可以尝试降低Java堆大小或增加大页面数来解决

参考内容