Hugepagesとは?
Hugepages は Linux のメモリー管理機能の一部です(他の OS でも似た機能を持っています)。Linux では通常 4KB 単位でメモリーをページテーブルで管理します。しかしページテーブルのサイズは有限であり、大規模メモリー環境ですべてのメモリーを 4KB 単位で管理すると、ページテーブルの管理負荷や TLB (Translation Lookaside Buffer) キャッシュのヒット率が下がるなどの弊害があります。
このためメモリーを管理するページのサイズを拡大(2MB)して、ページテーブルを小さくし、TLB のヒット率を上げる機能が提供されました(Hugepages)。RDBMS は大容量のメモリーを必要とするため、Hugepages の恩恵を受けやすいといえます。このためOracle Database をはじめ、多くの RDBMS で HugePages の利用をサポートしています。
Hugepagesには利点もありますが、欠点もあります。
- スワップアウトされません(利点にもなります)
- アプリケーションが利用を意識する必要があります
- 通常のメモリー領域と Hugepages 領域の両方を管理する必要があります
Oracle Database では SGA の領域を Hugepages 上のマップすることができます。制約としては、AMM (Automatic Memory Management) 機能が利用できません。このため初期化パラメーター memory_target, memory_max_target に 0 を指定する必要があります。
SQL> ALTER SYSTEM SET memory_target=0 SCOPE=SPFILE;
System altered.
SQL> ALTER SYSTEM SET memory_max_target=0 SCOPE=SPFILE;
System altered.
SQL> EXIT
$
$ srvctl stop database -d O19A
$ srvctl start database -d O19A
$
Transparent Hugepages
Hugepages の利用はアプリケーションが意識する必要があります。例えば mmap システムコールのマップを Hugepages 領域に置くには、MAP_HUGETLB をパラメーターに指定する必要があります。アプリケーションに Hugepages を意識させずに利用させる機能が Transparent Hugepages ですが、Oracle Database では利用は推奨されません。マニュアル には以下のように示されています。
インストールを開始する前に、透過的な HugePages を無効にすることをお薦めします。
Red Hat Enterprise Linux 7 で Transparent Hugepages を常に無効にするには、/etc/default/grub ファイルを修正します。GRUB_CMDLINE_LINUX パラメーターに transparent_hugepage=never を追記します。その後 grub2-mkconfig コマンドを実行し、OS を再起動します。
# vi /etc/default/grub
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="rd.lvm.lv=rhel/root rd.lvm.lv=rhel/swap rhgb quiet transparent_hugepage=never"
GRUB_DISABLE_RECOVERY="true"
#
# grub2-mkconfig -o /boot/grub2/grub.cfg
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-3.10.0-957.el7.x86_64
Found initrd image: /boot/initramfs-3.10.0-957.el7.x86_64.img
Found linux image: /boot/vmlinuz-0-rescue-fba6994c21b54b7a8921e313cde69169
Found initrd image: /boot/initramfs-0-rescue-fba6994c21b54b7a8921e313cde69169.img
done
#
Transparent Hugepages が無効であることを確認します。
# cat /sys/kernel/mm/transparent_hugepage/enabled
always madvise [never]
ユーザー設定
Hugepages を利用するユーザー(Oracle Database では通常 oracle ユーザー)にHugepages の利用量制限を指定します。memlock 制限の容量を物理メモリーよりも少しだけ少ない値(90% 以上)に指定します。
# grep MemTotal /proc/meminfo
MemTotal: 8174100 kB
#
# grep memlock /etc/security/limits.conf
oracle soft memlock 8100000
oracle hard memlock 8100000
#
# su - oracle
$ ulimit -l
8100000
$
Hugepages のサイズ
Hugepages のサイズは、カーネルパラメーター vm.nr_hugepages にページ数を指定します。
適切な値は、マニュアル に記載されている以下のスクリプトを実行します。一部 Red Hat Enterprise Linux 7.6用にカーネルのバージョンを修正しています(3.8 -> 3.10)。
# cat hugepages_settings.sh
#!/bin/bash
#
# hugepages_settings.sh
#
# Linux bash script to compute values for the
# recommended HugePages/HugeTLB configuration
#
# Note: This script does calculation for all shared memory
# segments available when the script is run, no matter it
# is an Oracle RDBMS shared memory segment or not.
# Check for the kernel version
KERN=`uname -r | awk -F. '{ printf("%d.%d\n",$1,$2); }'`
# Find out the HugePage size
HPG_SZ=`grep Hugepagesize /proc/meminfo | awk {'print $2'}`
# Start from 1 pages to be on the safe side and guarantee 1 free HugePage
NUM_PG=1
# Cumulative number of pages required to handle the running shared memory segments
for SEG_BYTES in `ipcs -m | awk {'print $5'} | grep "[0-9][0-9]*"`
do
MIN_PG=`echo "$SEG_BYTES/($HPG_SZ*1024)" | bc -q`
if [ $MIN_PG -gt 0 ]; then
NUM_PG=`echo "$NUM_PG+$MIN_PG+1" | bc -q`
fi
done
# Finish with results
case $KERN in
'2.4') HUGETLB_POOL=`echo "$NUM_PG*$HPG_SZ/1024" | bc -q`;
echo "Recommended setting: vm.hugetlb_pool = $HUGETLB_POOL" ;;
'2.6'|'3.10') echo "Recommended setting: vm.nr_hugepages = $NUM_PG" ;;
*) echo "Unrecognized kernel version $KERN. Exiting." ;;
esac
# End
スクリプトとして保存し、実行すると現在稼働している Oracle Database インスタンスが使っている共有メモリーの容量から、適切な Hugepages のページ数を計算して出力します。
# sh hugepages_settings.sh
Recommended setting: vm.nr_hugepages = 1205
カーネルパラメーター設定後に Oracle Database インスタンスを起動することで、インスタンスのSGAを Hugepages にマップすることができます。以下の例では全部で1,205 ページ利用でき、15 ページ余裕があります。
# grep Huge /proc/meminfo
AnonHugePages: 0 kB
HugePages_Total: 1205
HugePages_Free: 15
HugePages_Rsvd: 11
HugePages_Surp: 0
Hugepagesize: 2048 kB
Hugepages 関連のログ
正常時
SGA が Hugepages を使用したかどうかは、インスタンス起動時の alert ログに出力されます。
下記は、正常に Hugepages が利用できた場合のログです。
**********************************************************************
2019-07-08T20:48:51.322293-04:00
Dump of system resources acquired for SHARED GLOBAL AREA (SGA)
2019-07-08T20:48:51.322496-04:00
Per process system memlock (soft) limit = 7910M
2019-07-08T20:48:51.322604-04:00
Expected per process system memlock (soft) limit to lock
instance MAX SHARED GLOBAL AREA (SGA) into memory: 2402M
2019-07-08T20:48:51.322844-04:00
Available system pagesizes:
4K, 2048K
2019-07-08T20:48:51.323126-04:00
Supported system pagesize(s):
2019-07-08T20:48:51.323232-04:00
PAGESIZE AVAILABLE_PAGES EXPECTED_PAGES ALLOCATED_PAGES ERROR(s)
2019-07-08T20:48:51.323339-04:00
4K Configured 4 4 NONE
2019-07-08T20:48:51.323565-04:00
2048K 1205 1201 1201 NONE
2019-07-08T20:48:51.323671-04:00
**********************************************************************
ログ出力 | 説明 |
---|---|
Per process system memlock (soft) limit | ユーザーのmemlock制限 |
instance MAX SHARED GLOBAL AREA (SGA) into memory | インスタンスのSGA量 |
Available system pagesizes: | サポートしているページのサイズ |
Supported system pagesize(s) | ページサイズ毎の利用状況 |
不足時
初期化パラメーター use_large_pages がデフォルト値の TRUE になっている場合、Hugepages の量が足りなくてもエラーにはならず、できる範囲で Hugepages から取得されます。その際には追加を推奨するログが出力されます。下記は、必要な Hugepages 1201 ページに対して 600 ページしか利用できない場合のログです。最終的に 597 ページが確保され、RECOMMENDATION 部分が追記されています。
Supported system pagesize(s):
2019-07-08T21:39:55.054267-04:00
PAGESIZE AVAILABLE_PAGES EXPECTED_PAGES ALLOCATED_PAGES ERROR(s)
2019-07-08T21:39:55.054375-04:00
4K Configured 4 309127 NONE
2019-07-08T21:39:55.054652-04:00
2048K 600 1201 597 NONE
2019-07-08T21:39:55.054764-04:00
RECOMMENDATION:
2019-07-08T21:39:55.054870-04:00
1. For optimal performance, configure system with expected number
of pages for every supported system pagesize prior to the next
instance restart operation.
2019-07-08T21:39:55.063104-04:00
**********************************************************************