/proc/sys/vm/overcommit_memory
Linuxで最大値を制御します
たとえば、Ubuntu 19.04では、を使用して実装されていることが簡単にわかりますmalloc
mmap(MAP_ANONYMOUS
strace
。
次に、最大割り当てを制御するman proc
方法について説明します。/proc/sys/vm/overcommit_memory
このファイルには、カーネル仮想メモリアカウンティングモードが含まれています。値は次のとおりです。
- 0:ヒューリスティックなオーバーコミット(これがデフォルトです)
- 1:常にオーバーコミットし、チェックしない
- 2:常にチェックし、オーバーコミットしない
モード0では、MAP_NORESERVEを使用したmmap(2)の呼び出しはチェックされず、デフォルトのチェックは非常に弱く、プロセスが「OOM-killed」になるリスクがあります。
モード1では、カーネルは、メモリが実際になくなるまで、常に十分なメモリがあるふりをします。このモードの使用例の1つは、大規模なスパースアレイを採用する科学計算アプリケーションです。2.6.0より前のLinuxカーネルバージョンでは、ゼロ以外の値はモード1を意味します。
モード2(Linux 2.6以降で使用可能)では、割り当てることができる仮想アドレス空間の合計(/ proc / meminfoのCommitLimit)は次のように計算されます。
CommitLimit = (total_RAM - total_huge_TLB) * overcommit_ratio / 100 + total_swap
どこ:
- total_RAMは、システム上のRAMの合計量です。
- total_huge_TLBは、巨大なページ用に確保されているメモリの量です。
- overcommit_ratioは、/ proc / sys / vm/overcommit_ratioの値です。と
- total_swapは、スワップスペースの量です。
たとえば、16GBの物理RAM、16GBのスワップ、巨大なページ専用のスペースがなく、overcommit_ratioが50のシステムでは、この式は24GBのCommitLimitを生成します。
Linux 3.14以降、/ proc / sys / vm / overcommit_kbytesの値がゼロ以外の場合、CommitLimitは代わりに次のように計算されます。
CommitLimit = overcommit_kbytes + total_swap
/ proc / sys / vm/admiin_reserve_kbytesおよび/proc/ sys / vm/user_reserve_kbytesの説明も参照してください。
5.2.1カーネルツリーのDocumentation/vm / overcommit-accounting.rstにもいくつかの情報がありますが、少し少なくなります。
Linuxカーネルは、次のオーバーコミット処理モードをサポートしています
0
ヒューリスティックなオーバーコミット処理。アドレス空間の明らかなオーバーコミットは拒否されます。一般的なシステムに使用されます。オーバーコミットを許可してスワップの使用量を減らしながら、深刻なワイルドアロケーションが失敗することを保証します。このモードでは、rootはわずかに多くのメモリを割り当てることができます。これがデフォルトです。
1
常にオーバーコミットします。一部の科学アプリケーションに適しています。古典的な例は、スパース配列を使用し、ほぼ完全にゼロページで構成される仮想メモリに依存するコードです。
2
オーバーコミットしないでください。システムの合計アドレス空間コミットは、スワップ+構成可能な量(デフォルトは50%)の物理RAMを超えることはできません。使用量にもよりますが、ほとんどの場合、これはページへのアクセス中にプロセスが強制終了されないことを意味しますが、必要に応じてメモリ割り当てに関するエラーを受け取ります。
すべてのページを初期化することなく、将来的にメモリ割り当てが利用可能になることを保証したいアプリケーションに役立ちます。
最小限の実験
最大許容値は次のように簡単に確認できます。
main.c
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char **argv) {
char *chars;
size_t nbytes;
/* Decide how many ints to allocate. */
if (argc < 2) {
nbytes = 2;
} else {
nbytes = strtoull(argv[1], NULL, 0);
}
/* Allocate the bytes. */
chars = mmap(
NULL,
nbytes,
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS,
-1,
0
);
/* This can happen for example if we ask for too much memory. */
if (chars == MAP_FAILED) {
perror("mmap");
exit(EXIT_FAILURE);
}
/* Free the allocated memory. */
munmap(chars, nbytes);
return EXIT_SUCCESS;
}
GitHubアップストリーム。
コンパイルして実行し、1GiBと1TiBを割り当てます。
gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -o main.out main.c
./main.out 0x40000000
./main.out 0x10000000000
次に、割り当て値を試して、システムで何が許可されているかを確認できます。
(デフォルト)の正確なドキュメントが見つかりません0
が、32GiB RAMマシンでは、1TiBの割り当てが許可されていません。
mmap: Cannot allocate memory
ただし、無制限のオーバーコミットを有効にすると、次のようになります。
echo 1 | sudo tee /proc/sys/vm/overcommit_memory
その後、1TiBの割り当ては正常に機能します。
モード2
は十分に文書化されていますが、それを検証するために正確な計算を実行するのは面倒です。しかし、実際には、次のことについて割り当てることが許可されていることを指摘しておきます。
overcommit_ratio / 100
合計RAMの、そしてデフォルトであるので、合計RAMの約半分を割り当てることができますovercommit_ratio
。50
VSZvsRSSおよびメモリ不足キラー
これまで、仮想メモリを割り当てました。
ただし、もちろん、ある時点で、これらのページを十分に使用すると、Linuxはいくつかのプロセスの強制終了を開始する必要があります。
Linuxのメモリ管理におけるRSSとVSZとは何ですか?