大規模(AP/DB) サーバーでのLarge Pageの使用のすすめ

近年はメモリも安くなり、性能を向上させるために多量のメモリを使うことで性能を維持するのは、ある程度の大規模環境であれば一般的なことではないかと思います。特に、JVMOracleなどで多量のメモリを使うアプリケーションでは、ヒープサイズが数Gb-数十Gbだったり、buffer cacheのサイズが数十Gbだったりといったことも多くなっているのではないかと思います。

このような場合には、Large Pageの使用により、以下の3点の理由から性能が向上するケースがあります。

1ページのサイズが512倍と大きくなるため、TLBでカバーされる範囲が大きくなるため、キャッシュヒット率が向上します。ミスヒット時のペナルティは大きいので、これは一つ大きな効果があります。

また、1pageあたり4kで管理されていたメモリが、HugePageにより1pageあたり2mbになるわけで、メモリ容量をアロケーションする回数は1/512になるので、メモリアロケーションが高速になります。

さらに、TLBミスヒットした際に、2Mbの場合にページ階層が4->3になるため、アドレス変換も高速になるというわけです。

Large Pageの使用は、I/O性能の問題は解決できていて、問題がCPU/メモリに移っているケースでないとあまり効果は見られません。非常に早いディスクを使っているケースやほぼ全ての処理がメモリ上で行われるケースでは大きな効果が出ます。例えば、JVMではGC回数/時間の削減という形で非常に効果が見えるので、x64環境でGCに困っている方は試してみられることをお勧めします。

Large Pageを使用するための設定方法

仮に6Gb程度のヒープサイズを確保したとしましょう。
この場合、/etc/sysctl.confを変更します。

次のように設定します。

8Gb shared memory segment sizeを確保すると、1024 * 1024 * 1024 * 8 = 8589934592 のbyte数が必要なので、

kernel.shmmax = 8589934592

と設定します

また、hugetlbが使えるように、groupのIDを設定します。
java, mysql, oracleなどのユーザーのgroup idを次のように設定します。

vm.hugetlb_shm_group = <group id>

次にlarge pageのページ数を設定します。確保するメモリは6Gbなので、次のように計算します。

6Gb/ 2Mb = 3072 pages

設定は次のようにして設定します

vm.nr_hugepages = 3072

最後に物理メモリにpinします

javauser       soft  memlock     6291456
javauser       hard  memlock     6291456

最後にsysctl -p で設定を反映して、cat /proc/meminfo でHugePage数が設定できているかを確認して、3072が設定できていれば完了です。このページ数はサンプルですので、ページ数は実際の規模にあわせて設定してください。

Javaで使う場合には、上記に加えて、 XX:+UseLargePagesをJVMオプションに加えます。
Oracleなどで使う場合には、初期化パラメータにuse_large_pages=onlyを設定して使います。

また、この設定により、HugePageがRAMにPINされるため、ページアウトが起きなくなります。非常に大きなSGAサイズを確保しており、OSでのpage out回数の問題で性能が劣化するような大規模なトランザクションを扱っているケースなどでも効果があります。