Uwalnianie pamięci RAM z śmieci

Wszyscy doskonale znamy specyfikę zagospodarowania pamięci przez kernel Linuksa. Podczas gdy osoby początkujące zżymają się, że większość poleceń sprawdzających wykazuje zużycie pamięci na poziomie 95%, my cieszymy się, że nieużywana pamięć przeznaczana jest na bufory i pamięć podręczną operacji I/O. Wiemy też bardzo dobrze, że gdy wzrośnie zapotrzebowanie na pamięć, kernel zluzuje zaalokowane na swoje potrzeby zasoby. Co jednak w przypadku, gdy tak się nie dzieje, a sprzęt z nikczemną ilością pamięci pracuje coraz to mozolniej?

Powodów dla których kernel postanawia zatrzymać zarezerwowaną pamięć RAM, może być kilka – mniej lub bardziej zasadnych w naszym odczuciu (kwestia dystrybucji, wersji kernela, operacji dyskowych, itp.). Jeżeli jesteśmy przekonani, że pamięć cache systemu plików stoi na drodze naszego dobrego samopoczucia i sprawności użytkowania komputera, pozostaje nam jedno wyjście. Przekonać kernel, aby cyklicznie zwalniał te zasoby. Bo bądźmy szczerzy – jak sama nazwa wskazuje, pamięć cache przyśpiesza operacje I/O przy dużej ilości trafień (czyli powtórzeń dostępu do tej samej porcji danych), a nie samym swoim istnieniem. Niestety, z braku statystyk wykorzystania pamięci cache, jednym sposobem sprawdzenia jak to wygląda w naszym przypadku (czyli czy specyfika naszej pracy, to np. odczytywanie z dysku tych samych danych, czy też nie), to testy i próby. Brzmi odpychająco? Ale to nic skomplikowanego.

Zaczynamy od tego, że upewniamy się o dramatycznym stanie wykorzystania pamięci RAM na cache i bufory. Wydając polecenie ‘free -m’ otrzymujemy zużycie pamięci:

$# free -m
             total       used       free     shared    buffers     cached
Mem:          3946       2521       1425          0         20        794
-/+ buffers/cache:       1705       2240
Swap:         4502          0       4502

Choć powyższe nie wygląda w moim przypadku dramatycznie, to osoby z 1 – 2GB pamięci mogą zauważyć u siebie nieciekawe proporcje cached w stosunku do total. Aby przekonać kernel o zwolnieniu tych zasobów, wykorzystamy… mechanizm odpowiadający za zwolnienie tych zasobów (Drop_Caches):

sudo sync
sudo echo 3 > /proc/sys/vm/drop_caches
sudo sysctl -w vm.drop_caches=3

Sprawdzamy za pomocą ‘free -m’ efekty:

$# free -m
             total       used       free     shared    buffers     cached
Mem:          3946       1944       2001          0          1        126
-/+ buffers/cache:       1816       2130
Swap:         4502          0       4502

I jak widać, jest luźniej (kolumna buffers i cached). Należy pamiętać, że tym samym nasz komputer zwiększy ilość odwołań do dysku twardego (gdy będzie musiał coś odczytać), dlatego wspominałem wcześniej o konieczności samodzielnego wykonania własnego bilansu zysków i strat.

No dobrze, komendy może i ciekawe, ale za jakiś czas ponownie kolumny ‘cached’ i ‘buffers’ się zapełniają niezliczoną liczbą bajtów. Dlatego gdy stwierdzimy, że to rozwiązanie jest dla nas dobre i skuteczne, wykorzystujemy Crona, by co 5 – 15 minut automatycznie wykonał to, co wpisywaliśmy powyżej. Zlecamy mu co następuje:

sudo gedit /etc/cron.d/dropcaches

… i wklejamy:

*/5 * * * * root sync && echo 3 > /proc/sys/vm/drop_caches

Zapisujemy. Powyższa linijka spowoduje, że Cron co 5 minut (*/5, ale możemy też co 10 minut */10 – lub */15) wykona nasze polecenie (sync && echo 3 (…)).

Jak wspomniałem, osoby z większą ilością pamięci pewnie nawet nie muszą się zastanawiać nad takim rozwiązaniem – o ile nie używają dystrybucji z ‘defektem’ luzowania buforów dyskowych. Ale niektóre słabsze konfiguracje (komputer z 1GB pamięci słabszy… jak to brzmi…) mogą poczuć zbawienny wpływ powyższych machinacji.