Jak działa vm.overcommit_memory?

49

Kiedy używam ustawień domyślnych:

vm.overcommit_memory = 0
vm.overcommit_ratio = 50

Mogę odczytać te wartości z /proc/meminfopliku:

CommitLimit:     2609604 kB
Committed_AS:    1579976 kB

Ale kiedy zmieniam vm.overcommit_memoryz 0na 2, nie mogę uruchomić tego samego zestawu aplikacji, który mógłbym uruchomić przed zmianą, szczególnie amaroka. Musiałem zmienić vm.overcommit_rationa 300, aby limit mógł zostać zwiększony. Teraz, gdy uruchamiam amarok, /proc/meminfopokazuje:

CommitLimit:     5171884 kB
Committed_AS:    3929668 kB

Ta maszyna ma tylko 1 GB pamięci RAM, ale amarok działa bez problemów, gdy vm.overcommit_memoryjest ustawiony na 0. Ale w przypadku ustawienia go 2, Amarok musi przydzielić ponad 2 GB pamięci. Czy to jest normalne zachowanie? Jeśli tak, czy ktoś mógłby wyjaśnić, dlaczego na przykład firefox (który zużywa 4-6x więcej pamięci niż amarok) działa w ten sam sposób przed zmianą i po niej?

Michaił Morfikow
źródło

Odpowiedzi:

66

Dokumentację można znaleźć w man 5 proc( lub na kernel.org ):

/proc/sys/vm/overcommit_memory
       This file contains the kernel virtual memory accounting mode.
       Values are:

              0: heuristic overcommit (this is the default)
              1: always overcommit, never check
              2: always check, never overcommit

       In mode 0, calls of mmap(2) with MAP_NORESERVE are not
       checked, and the default check is very weak, leading to the
       risk of getting a process "OOM-killed".

       In mode 2 (available since Linux 2.6), the total virtual
       address space that can be allocated (CommitLimit in /proc/mem‐
       info) is calculated as

           CommitLimit = (total_RAM - total_huge_TLB) *
                         overcommit_ratio / 100 + total_swap

Prosta odpowiedź jest taka, że ​​ustawienie overcommit na 1 spowoduje ustawienie sceny tak, że gdy program wywoła coś w rodzaju malloc()alokacji fragmentu pamięci ( man 3 malloc), zawsze odniesie sukces, niezależnie od tego, czy system wie, że nie będzie miał całej pamięci spytany o.

Podstawową koncepcją do zrozumienia jest idea pamięci wirtualnej . Programy widzą wirtualną przestrzeń adresową, która może, ale nie musi, być odwzorowana na rzeczywistą pamięć fizyczną. Wyłączając sprawdzanie nadpisywania, nakazujesz systemowi operacyjnemu założyć, że zawsze jest wystarczająca ilość pamięci fizycznej do utworzenia kopii zapasowej przestrzeni wirtualnej.

Przykład

Aby podkreślić, dlaczego czasami może to mieć znaczenie, zapoznaj się z wytycznymi Redis, dlaczego vm.overcommit_memorywarto ustawić na 1.

Kyle Brandt
źródło
2
Ale czy wartość nie powinna Committed_ASbyć taka sama w obu przypadkach?
Michaił Morfikow
@MikhailMorfikov: Teoretycznie tak sądzę, ale kto wie, co robią te programy. Chciałbym zobaczyć bardziej kontrolowane środowisko z prostym programem, który po prostu przydziela np. Gigantyczną pamięć RAM przez Malloc. A następnie uruchom test po ponownym uruchomieniu komputera między testami.
Kyle Brandt
Ok, więc zostanę 0na razie.
Michaił Morfikow
2
@MikhailMorfikov: Tak, praktycznie uważam, że 0 ma sens. W moim środowisku włączam 1 tylko dla Redis, który robi rzeczy tam, gdzie się spodziewa , prosi o dużo więcej pamięci, której używa ze względu na fork (). Dziecko w zasadzie używa wszystkich tych samych stron pamięci, ale Linux nie wie, że mówi, że aby być bezpiecznym, musi założyć, że użyje 2x pamięci (jeśli chcesz dowiedzieć się więcej: redis.io/topics/faq )
Kyle Brandt
czy ostatnie zdanie w odpowiedzi nie powinno zaczynać się od „przez włączenie nadpisania”? ponieważ ustawienie go na 1 oznacza, że ​​prosisz go o nadmierne zaangażowanie, prawda?
asgs