pl  |  en

Rozliczanie pamięci

Na MT 1.0 nie było żadnego specjalnego mechanizmu rozliczania pamięci — liczyliśmy wszystko ręcznie, sumując PSS poszczególnych procesów. Nie mieliśmy żadnej możliwości policzenia wielkości cache’u, którą dany użytkownik zajmował. Z jednej strony, liczyliśmy to, na co użytkownik ma jakiś wpływ, a z drugiej, nie liczyliśmy wszystkiego, czego używa (mała aplikacja licząca w kółko MD5 z wielogigabajtowego systemu plików użyje grosze PSS/RSS i dużo cache, potencjalnie szkodząc innym użytkownikom).

Na MT 2.0 wykorzystujemy wbudowany w jądro od jakiegoś czasu mechanizm memcg (memory control groups). W ten sposób mamy zawsze pełne i aktualne informacje o zużyciu pamięci.

Zliczamy trzy rodzaje pamięci:

  • RSS (było na MT 1.0) – pamięć bezpośrednio używana przez aplikacje
  • cache (brak na MT 1.0) – pamięć nie używana jawnie przez aplikacje, ale trzyma dane załadowane z dysku (żeby ich nie ładować za każdym razem jak są potrzebne)
  • swap (brak na MT 1.0) – pamięć, która należy do aplikacji, ale nie była potrzebna aż tak bardzo, żeby zajmować pamięć i została wyrzucona na dysk.

Zliczane zużycie pamięci przez tę samą aplikację na MT 2.0 może być większe niż na MT 1.0, dlatego wartości pamięci w nowych opcjach są 2x większe niż w analogicznych opcjach starej oferty. Na zajętą pamięć ma również wpływ 64bitowy system (wcześniej 32bit).

Mamy dwa rodzaje limitów:

  • trwały (tyle, ile wynika z opcji)
  • tymczasowy (240 MB, chyba że w opcji jest więcej).

Wszystkie procesy startują w grupie tymczasowej. Po 5 minutach działania przenosimy je do grupy trwałej. Ma to na celu danie trochę większej pamięci krótko żyjącym zadaniom typu instalacja czegoś.

Kernel jest leniwy w zwalnianiu pamięci (i to dobrze, bo niepotrzebne ruchy generują tylko I/O, jak okaże się, że jednak trzeba było nie zwalniać), więc w memcg mogą czasem zostać nieużywane rzeczy, które bardziej się opłaca trzymać niż aktywnie wyrzucać. Dlatego na wykresach może być widać zajętą pamięć, nawet jeżeli w danym momencie na koncie nie jest nic uruchomione. Zajęta pamięć zostanie zwolniona, jeżeli faktycznie będzie potrzebna.

Zamiast własnych narzędzi do limitowania pamięci, jak było na MT 1.0, polegamy teraz na systemowym OOM killerze. Wchodzi on w życie, kiedy w memcg skończy się pamięć i nie da się jej łatwo zwolnić (nie ma już ani śmieci do łatwego wyrzucenia, ani np. cache do zwolnienia). Proces do ubicia wybierany jest przez kernel i nie musi to akurat być największy proces (chociaż najczęściej tak będzie).