オーバーコミット

February 05, 2020

仮想空間のオーバーコミット量のチューニング

複数のプロセスがメモリを奪い合う環境を考えた時に、システム全体の仮想空間量を制限する必要がある。プロセスに無尽蔵に仮想空間を割り当てても実際に使用しない限りは物理メモリ量に影響は無いものの、システムの安定性を考えると割り当てる仮想空間のサイズは物理メモリの量である程度裏付けされているべきである。物理メモリの裏付けのない仮想空間を大量に割り当てて、仮に一斉に大量の物理ページ割り当てが行われるというシチュエーションも考慮した方が良い。
Linux にはオーバーコミット (物理メモリ量を超えてどの程度仮想空間割り当てを許すか) を決めるパラメータがあり、以下の /proc エントリでその制御を行う。

  • /proc/sys/vm/overcommit_memory
  • /rpoc/sys/vm/ocercommit_ratio

/proc/sys/vm/overcommit_memory は仮想空間割り当てのポリシーを制御するパラメータとなり、以下 3 つの値を設定することが可能。

  • OVERCOMMIT_GUESS (0)
  • OVERCOMMIT_ALWAYS (1)
  • OVERCOMMIT_NEVER (2)

デフォルトは OVERCOMMIT_GUESS となる。

$ cat /proc/sys/vm/overcommit_memory   
0  

また、例えば OVERCOMMIT_NEVER にするのであれば以下のように変更する。

$ sudo bash -c "echo 2 > /proc/sys/vm/overcommit_memory"  
$ cat /proc/sys/vm/overcommit_memory   
2  

/proc/sys/vm/overcommit_ratio には、オーバーコミットを許す仮想空間の大きさをそう物理メモリ量に対するパーセンテージで指定し、デフォルト値は 50 となる。つまり、そう物理メモリ量の 150% まで仮想空間を割り当てることができる。

$ cat /proc/sys/vm/overcommit_ratio   
50  

OVERCOMMIT_GUESS

このパラメータが指定された場合は、空きメモリ、ページキャッシュ量、空きスワップ量、回収可能なスラブ量などをもとに回収可能なページ数を予測し、仮想空間割り当て要求量がそれより小さい場合には割り当てが成功する。
OVERCOMMIT_GUESS の場合、割り当て可能な仮想空間の大きさはほぼ物理メモリ + スワップサイズの合計となる。つまり、物理メモリが 2 GiB でスワップ領域を 2 GiB 中 1 GiB 使用している場合は、約 3 GiB 分の大きさの仮想空間割り当てが可能となる。

OVERCOMMIT_ALWAYS

OVERCOMMIT_ALWAYS の場合、常に仮想空間割り当てが成功する。過大な仮想空間要求に対しても仮想空間を割り当てる。これは実装物理メモリ量と完全に無関係な形で仮想空間を利用したい場合に使用する。

OVERCOMMIT_NEVER

OVERCOMMIT_NEVER の場合、より厳しく割り当て可能な仮想空間量を管理する。
まず、システム全体で割り当て済みの仮想空間量を記録しておく。この値は厳密にシステムで集中管理されており、仮想空間の割り当て時や開放時に再計算する。
なお、この値は /proc/meminfo の Committed_AS となる。

$ cat /proc/meminfo | grep Committed_AS  
Committed_AS:     460892 kB  

仮想空間の大きさの計算についても他のパラメータより厳しくなっている。例えば mmap システムコールに MAP_NORSERVE を設定した仮想空間量は、OVERCOMMIT_GUESS の場合 Committed_AS に加算されない。しかし、OVERCOMMIT_NEVER の場合は Comitted_AS に加算される。MAP_NORSERVE を指定された領域も物理メモリ割り当ての可能性がある仮想空間として扱う。

次に、全物理メモリ量 + 総スワップ量 に、/proc/sys/vm/overcommit_ratio で指定した比率を積み増しした値を割り当て可能な仮想空間総量とする。この値は /proc/meminfo の CommitLimit で確認可能。

$ cat /proc/meminfo | grep CommitLimit  
CommitLimit:    36426076 kB  

CommitLimit の値は OVERCOMMIT_NEVER を利用しているときにのみ有効となる。

仮想空間の割り当て要求時、Committed_AS の仮想空間量が CommitLimit を超過している場合、割り当てには失敗する形となる。


 © 2023, Dealing with Ambiguity