Jak obliczyć wolną pamięć RAM w Linuksie?

Ile mam wolnej pamięci w systemie? to częste pytanie i użytkowników desktopów, i administratorów. Na każde pytanie istnieje prosta, błędna odpowiedź i podobnie jest w tym przypadku, choć ustalanie ilości wolnej pamięci RAM wydaje się trywialną sprawą. Większość ludzi korzysta z polecenia free, którego przykładowy wynik może wyglądać następująco (desktop):

total       used       free     shared    buffers     cached
Mem:       3926996    3614388     312608          0      82656    1305692
-/+ buffers/cache:    2226040    1700956
Swap:      1022964      20480    1002484

Typowa interpretacja byłaby zapewne w tym przypadku taka, że wolnych jest 312608 kB RAM. Niezupełnie jest to prawdą. Tzn. tyle pamięci faktycznie jest zupełnie nieużywanej, ale tak naprawdę w razie potrzeby dla aplikacji dostępne jest znacznie więcej pamięci i należałoby raczej patrzeć na drugi wiersz, nie pierwszy, czyli bliższym prawdy wynikiem jest, że wolnych w tym przypadku jest 1700956 kB RAM.

W przypadku serwerów z Linuksem, ilość wolnej pamięci łatwiej odczytać, szczególnie na potrzeby skryptów, z /proc/meminfo/:

cat /proc/meminfo | head -n 5
MemTotal:        3926996 kB
MemFree:          296944 kB
MemAvailable:    1589592 kB
Buffers:           82692 kB
Cached:          1305316 kB

Patrząc na wartości z /proc/meminfo, ilość zajętej i wolnej pamięci RAM można liczyć w następujący sposób:

Free RAM = MemFree + Buffers + Cached
Used RAM = MemTotal - (MemFree + Buffers + Cached)

Jednak i to niezupełnie jest prawdą, bo do w skład Cached wchodzą np. obszary używane przez tmpfs, które nie mogą być zwolnione. Dlatego niedawno w /proc/meminfo dodano kolejną wartość MemAvailable, której zadaniem jest podawanie wprost ilości dostępnej do wykorzystania przez programy (czyli, potocznie, wolnej) pamięci. Jeśli taka wartość jest podana, to zamiast powyższych wzorów lepiej skorzystać z:

Free RAM = MemAvailable
Used Ram = MemTotal - MemAvailable

Linki:

  1. http://www.linuxatemyram.com/
  2. https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773

Praca na desktopie z małą ilością RAM po raz trzeci – zram.

W poprzednich wpisach było parę przemyśleń i sugestii poprawy komfortu pracy na desktopie wyposażonym w niewielką ilość pamięci RAM, bez finalnego rozwiązania choć z paroma trickami poprawiającymi pracę, więc pora na podejście trzecie do tematu, inspirowane przez kumpla z IRC, który sprzedał mi „newsa” o zram.

Od pewnego czasu (okolice kernela 2.6.37, jeśli dobrze widzę) w kernelu Linuksa obecny jest moduł zram, pozwalający na tworzenie kompresowanych urządzeń blokowych w pamięci RAM. Wykorzystać to można podobnie jak compcache, czyli do tworzenia kompresowanego obszaru pamięci, używanego przez system przed przeniesieniem danych na swap na dysku. Idea jest prosta – swap na dysku jest tragicznie wolny i obciąża I/O, procesor zwykle się trochę nudzi, zresztą nie będzie miał dużo więcej pracy, a ilość wolnej pamięci się zwiększy.

Ogólnie zram jest ideowym spadkobiercą compcache, ale wygląda mi na prostszy i ideowo, i w użyciu. No i jest obecny w kernelu. Idea działania jest prosta: tworzymy swap z wyższym priorytetem, niż swap na dysku, na urządzeniu blokowym umieszczonym w kompresowanym obszarze pamięci. Początkowo dane tradycyjnie są w RAM, w przypadku, gdy system musi korzystać z przestrzeni wymiany, umieszcza je najpierw na swapie w RAM, a dopiero później – tradycyjnie – na swapie na dysku.

Prosty skrypt realizujący powyższe:

#!/bin/bash
modprobe zram
echo $((200*1024*1024)) > /sys/block/zram0/disksize # 200 MB
mkswap /dev/zram0
swapon -p 60 /dev/zram0

Kolejno: załadowanie modułu zram (można korzystać z parametrów), określenie rozmiaru dysku dla urządzenia /dev/zram0 na 200 MB (i jest to rozmiar swap, będący jednocześnie maksymalną wielkością zużytej pamięci, nie rozmiarem przeznaczonej pamięci na swap!), utworzenie swapu na urządzeniu  /dev/zram0, włączenie utworzonego swap z priorytetem 60.

Podobno efekty są świetne – zaczynam testy u siebie, wstępnie nie wygląda źle, na pewno niebawem podzielę się wrażeniami (jako update do tego wpisu) po dłuższym teście. Jeśli chodzi o rozmiar swap dla modułu zram, to zacząłbym od 10-20% całości RAM (u mnie 200 MB przy 1 GB RAM). Z tego co zauważyłem, skompresowane dane zajmują w praktyce ok. 40-50% oryginalnych.

Parę przydatnych poleceń diagnostycznych:

  • cat /sys/block/zram0/compr_data_size – rozmiar danych po kompresji
  • cat /sys/block/zram0/orig_data_size – rozmiar nieskompresowanych danych
  • cat /sys/block/zram0/mem_used_total – całkowita ilość zużytej pamięci
  • swapon -s – rozmiar i wykorzystanie poszczególnych swap (inna jednostka!)

Linki w temacie, które zdecydowanie warto przejrzeć, jeśli ktoś jest bardziej zainteresowany:

Szczególnie ostatni wpis zawiera fajny, uwzględniający ilość procesorów skrypt startowy. Można rozważyć użycie po przeanalizowaniu. IMHO dla 1-2 procesorów trochę kosmiczne wartości będą, uzależnianie wielkości swap od ilości procesorów też jest średnie, ale poprawienie to nic trudnego. Za to obsługą utworzonego urządzenia blokowego zajmie się w tamtym wariancie więcej, niż jeden procesor. Z drugiej strony kto ma więcej niż dwa rdzenie i mało RAM?

Miałem obawy co do działania hibernacji (z użyciem pm-utils, z uswsusp miałem problem…) w takiej konfiguracji. Niepotrzebnie, bo wygląda, że działa OK – zapewne hibernacja jest na tyle inteligentna, że rozpoznaje, czy ma do czynienia z fizycznym urządzeniem blokowym.

Oczywiście swap to nie jedyne możliwe zastosowanie modułu zram – więcej przykładów w linku do wiki Gentoo.

Monitoring Tora w konsoli – howto.

Jak wiadomo m.in. z poprzedniego wpisu, prowadzę węzeł Tora. Bez połączeń wychodzących, czyli robię tylko za żuczka dokładającego jeden hop w ścieżce w celu zwiększenia anonimowości korzystających z tego programu. Od pewnego czasu miałem wrażenie, że jedyne, co robi mój Tor, to zajmuje pamięć (ponad 30% na biednym Dockstarze). Nie robiłem żadnych dokładnych statystyk, po prostu obserwowałem ilość ruchu na interfejsach, ale wyglądało, że jest mniej, niż kiedyś.

Postanowiłem sprawdzić, co się dzieje w rzeczywistości. Już kiedyś widziałem, że jest projekt arm czyli anonymizing relay monitor, ale wtedy nie było pakietów w Debianie, więc nie instalowałem, a pozwala on na znacznie więcej, niż tylko obejrzenie ilości ruchu, więc postanowiłem zainstalować arm.

W tej chwili paczka tor-arm jest dostępna w Debianie unstable (na stable instaluje się czysto), więc doinstalowałem ją (wajig install tor-arm). Samo uruchomienie (wpisanie arm) nic nie dało (używa domyślnej konfiguracji), więc po pierwsze, skopiowałem domyślną konfigurację (położenie w Debianie nieco inne niż podawane w manualu):

zcat /usr/share/doc/tor-arm/armrc.sample.gz > .arm/armrc

Nadal nic. Kolejna sprawa, to uruchomienie portu do kontroli w samym Torze, czyli dodanie w configu opcji:

ControlPort 9051

Po ponownym uruchomieniu arm jak najbardziej się połączył, ale ostrzega, że port do kontroli jest otwarty. Co prawda maszynka jest firewallowana, ale wypadałoby dodać hasło do zarządzania. Nie jest to trywialne i znalezienie zajęło mi dłuższą chwilę (chociaż jest w dokumentacji), więc opiszę. Najpierw generujemy hash hasła:

tor --hash-password jakieshaslo 

Otrzymujemy coś w stylu ciągu

16:2CCAAB2DEEB082CD60610B3BE6A0FF2A90EEFC92AD434C9C8CBFA42B0B

Następnie w konfiguracji Tora dodajemy linię

HashedControlPassword 16:2CCAAB2DEEB082CD60610B3BE6A0FF2A90EEFC92AD434C9C8CBFA42B0B

i restartujemy Tora (/etc/init.d/tor restart). Na koniec edytujemy ~.arm/armrc i uzupełniamy linię z startup.controlPassword, by miała postać:

startup.controlPassword jakieshaslo

Po zmianach okazało się, że miałem nosa i faktycznie niewiele się dzieje. Nawet bardzo niewiele. Praktycznie nic. Ponieważ kiedyś ruchu było więcej, postanowiłem sprawdzić, czy winnym nie jest ustawienie węzła jako bridge node. Bingo! Po zmianie od razu jest więcej ruchu. Zatem w chwili obecnej mój konfig Tora wygląda następująco:

ControlPort 9051
RelayBandwidthRate 20 KBytes
RelayBandwidthBurst 30 KBytes
ExitPolicy reject *:* # no exits allowed
ORPort 443
HashedControlPassword 16:2CCAAB2DEEB082CD60610B3BE6A0FF2A90EEFC92AD434C9C8CBFA42B0B

UPDATE: Przy okazji wygląda, że wyłączając tryb bridge node upiekłem dwie pieczenie na jednym ogniu. Po 16 godzinach zużycie pamięci RAM przez Tor wynosi ledwie 9%, zamiast wspomnianych 30%. Czyżby jakiś bug związany z trybem bridge? W każdym razie średni ruch upload i download teraz to po 50 Kbps, zużycie pamięci, które mnie trochę bolało mniejsze. Jednym słowem: lubię to! 😉