Velmi často se v různých fórech objevují dotazy ohledně paměťové náročnosti Linuxu. Pokusím se jednoduše objasnit, jak se to má v systému s pamětí.
Pod mým článkem o programu Htop se jeden čtenář ptá, jak je to s ukazateli paměti v Linuxu. Je z nich pochopitelně zmatený, protože pochopení těch položek je poměrně komplikované. Zkusím tedy nastínit, co znamenají a jak s nimi pracovat.
Abychom pochopili, která bije, potřebujeme určitý teoretický základ o procesech a jejich paměti. Každý proces může zabírat paměť na dvou místech: v RAM a ve swapu. Když systému dochází paměť, začne odkládat paměťové stránky z RAM na disk a tím ušetří systémovou paměť. Když chce proces danou paměťovou stránku použít, ta se automaticky načte zpět do RAM.
Linux šetří paměť. Takže pokud je některý kód potřeba vícekrát, je jeho paměť sdílena mezi více procesy. Paměť s binárním kódem je nastavena jen pro čtení, takže do ní nelze zapisovat a není problém ji tedy sdílet. Prakticky každý proces potřebuje systémovou knihovnu glibc, ta je mu tedy namapována, ale nekopíruje se. Zůstává v paměti jen jednou, ale ve svém virtuálním paměťovém prostoru ji vidí všichni.
Pokud se budete snažit z Linuxu vyrazit, kolik paměti doopravdy zabírá konkrétní proces, dostanete různé velmi rozdílné hodnoty, ze kterých zřejmě nebudete moudří. Tyto hodnoty zjistíte třeba pomocí ps
, top
či zmíněného htop
. Obvykle jsou čtyři: VIRT, RES, SHR a SWAP. Někdy poslední z nich chybí, ale to teď není podstatné. Podstatné je, co která z nich znamená.
Jako příklad si ukážeme obrazovku Htopu, která ukazuje, kolik mi právě v paměti zabírá spuštěná Java:
VIRT – Virtual image
Ukazuje veškerou paměť namapovanou procesem. Je to zcela jistě nejvyšší číslo, které o procesu dostanete. Jeho součástí je totiž kód, data, sdílené knihovny, odswapované stránky i soubory namapované do paměti. Toto číslo bývá někdy velmi vysoké, jak je vidět i na příkladovém obrázku. Proces Java na něm zabírá více VIRT paměti, než kolik je jí zabráno celkově (horní graf). Proč?
Jak jsme si řekli, Linux šetří paměť a tak například namapované soubory rovnou nenatahuje do paměti, ale dělá to až ve chvíli, kdy jsou některé jejich části skutečně potřeba. V praxi si tak může proces klidně namapovat celý několikagigabajtový soubor a systém se bude tvářit, že je celý tento soubor v paměti. Teprve až proces sáhne doprostřed této paměti a zkusí něco přečíst, systém potřebnou stránku načte a dá data k dispozici. Položka VIRT tedy obsahuje i velikost dat, která v paměti doopravdy nejsou, ale proces si na ně může v případě potřeby sáhnout. Jinými slovy určuje velikost jeho virtuálního paměťového prostoru.
RES – Resident size
Ukazuje skutečnou velikost paměti, kterou proces zabírá v paměti RAM. Ale pozor, to rozhodně není číslo, které hledáme. Potíž je v tom, že část této paměti je sdílena mezi procesy, jak jsme si už řekli.
Pokud tedy budeme mít dva programy po 20 MB a oba budou linkovat stejnou knihovnu o velikosti 10 MB, budou mít jejich RES dohromady 60 MB, přestože v paměti budou všechny tyto části dohromady zabírat jen 50 MB, protože stejnou paměť knihovny budou mít namapovány oba procesy.
SHR – Shared memory
Tento ukazatel zobrazuje právě tu část paměti procesu, kterou sdílí ještě s dalšími procesy. V případě obou našich příkladových procesů by to bylo 10 MB.
SWAP
Konečně poslední ukazatel zobrazuje množství paměti procesu, které se nachází v odkládacím souboru. Tato hodnota není součástí hodnoty RES, protože ta ukazuje jen data v RAM.
Na to je dost těžké odpovědět. Nejjednodušší je spočítat RES + SWAP – SHR. Tedy fyzicky zabranou paměť sečíst s odloženou částí a odečíst z ní sdílenou paměť. Tím dostaneme informaci o tom, kolik skutečného prostoru zabírá v RAM náš proces. Java z obrázku tedy reálně na paměťových čipech zabírá 178 MB, přestože má virtuálně namapován 1,2 GB.
Do těchto výpočtů ale nijak nezahrnujeme právě sdílenou paměť, která je sice k dispozici více procesům, ale v celkovém součtu obsazené paměti je nezanedbatelná. Můžeme se ale spokojit s tím, že tuto paměť nezabírá námi zkoumaný proces, protože by byla stejně zabraná kvůli potřebám jiného procesu. Snad jsem vám taje linuxové paměti alespoň trochu osvětlil.
pekny clanok, vdaka za objasnenie, bo tiez som mal vzdy rovnaky zmätok v tom.
akurat na margo toho RES+SWAP-SHR , tak na uvedenom priklade v HTOPe nikde nevidim hodnotu SWAP pre ten proces. je tam iba globalny ukazatel Swp s hodnotou 77/1906 MB nahore. cize swap nieco zozral, ale nevieme co?
super článek, zrovna včera jsem htop zkoumal, měl bych 2 dotazy:
1) jakým způsobem se dají filtrovat procesy v htop, jako je na screenshotu? já tam mám jenom vyhledávání pod klávesou F2
2) údaje o volné paměti se liší - např. já mám v htop volnych cca 250MB, ale příkazy free nebo top vypisují 70MB. pochopil jsem, že rozdíly jsou způsobené různým typem výpočtu a prezentace dat. zajímalo by mě tedy to, jakou hodnotu mám brát v potaz vzhledem k blížícímu se přetížení serveru
[2] 1) Pod F4 je funkce filter
2) Pokud to potřebujete přesně, vypište si to příkazem free
total used free shared buffers cached
Mem: 3828 3609 218 0 141 2112
-/+ buffers/cache: 1355 2473
Swap: 0 0 0
total->celkově k dispozici
used->Celkem použito
free->Naprosto neobsazeno
shared->paměť sdílená více procesy najednou
buffers->paměť využitá jako IO (tady už si nejsem tolik jist)
cached->cache pro rychlejší načítání dříve použitých procesů apod
V druhém řádku je využitá a volná paměť uvedena bez bufferů a cache...
Ahoj,
měl bych dva dotazy:
1)
Tuší někdo, zda jde z vmstat nebo z /proc vytáhnout podíl SHR na počet příslušejících procesů?
2)
co vlastně tedy reprezentuje třeba v htopu položka Mem? Je to součet RES všech procesů + SHR - SWAP? Pak ale zůstává nejasnost v SHR viz 1. dotaz
díky
[7] Informaci o vyuziti swapu konkretnim procesem vyctes v poslednich jadrech na /proc/PID/status (driv to neslo rozumne zjistit).
Jinak pekny clanek, skoda ze v blogu. Myslim si ze takove clanky patri na root vic, nez co se bezne publikuje. Vsadim se, ze tady jeste vznikne pekna a informacne bohata diskuse (narozdil od vlastnich clanku pochybneho obsahu).
Zdravím, mám jeden dotaz.
Pokud ve svém Cčkovém programu zavolám malloc(2048), mám de facto 2048B, ale ve skutečnosti mám jednu celou stránku, ta má zpravidla velikost 4096B, ale může mít klidně víc. Pokud aplikuji v článku zmíněný postup, dostanu velikost paměti skutečně alokovanou aplikací, nebo velikost paměti odpovídající vzorci (počet alokovaných stránek) * (velikost stránky)? Tipuju, že bych měl dostat to druhé.
Pozor na to, ze do VIRT se zapocitava i pamet rezervovana. Pokud nevite o co jde, tak jde o overcommit. Mohu si zaalokovat treba gigabajt, ale dokud si na tu pamet nesahnu, tak nikde neexistuje. Jako by na vsechny stranky byla namapovana jedna sdilena stranka se samymi nulami sdilena pomoci copy on write.
Stejne tak COW stranky jsou ve VIRT, pritom se sdili jen do prvniho zapisu.
[13.] At koukam, jak koukam, tak v manu furt nejak nevidim, jak donutit free k vypsani seznamu procesu a jejich odpovidajiciho prostoru na swapu, idealne s moznosti razeni podle nejakych kriterii, napriklad podle jmena procesu, podle velikosti obsazeneho swapu... Asi nemam to same free jako vy.
Ahoj all,
pěkný článek...
Nicměně jsem si chtěl právě nabité informace ověřit v praxi a něco mi tam neštýmuje .... naloguju na celkem vytíženou mysql, kouknu do htopu a vidím cca 20 procesů mysqld - VIRT 2980MB,RES 1010MB,SHR 7690 z čehož mi vyplívá,že by mysqlka měla požadovat asi 20GB fyzické ram ,přičemž v serveru mám jen 4GB. Hodnoty sdílené (SHR 7690) jsou malé , zanedbatelné...
Co teď? :)
Dík Dik
[1]
Pokud jde o ten swap a dalsi, tak se kouknete do /proc/self/smaps.
To je novejsi verze soubory maps. Novejsi kernely v souboru smaps zobrazuji i velikost swapu pro kazdy segment. Uplne nejnovejsi kernely dokonce zobrazuji i informaci o tom, ze pametovy region je zamceny - tzn. je oznaceny jako neswapovatelny.
PS: nekde na internetu se da stahnout script ps_mem.py ten zobrazuje proporcionalni(percentualni) velikost RAM u shared segmentu.
[16] To Htop ukazuje vlákna jednoho procesu, nedá se to sčítat, protože jde o jednu paměť, ve které běží několik vláken. Dá se to jednoduše vypnout, aby ukazoval jen procesy a ne jejich vlákna, takže tam pak to MySQL bude správně jednou.
F2 -> Display options -> Hide userland threads
RES-SHR je taky jen orientační. Na tom příkladu by to bylo 30-10=20, dohromady oba procesy tedy 40, místo skutečných 50, protože se vyloučí sdílená paměť úplně, místo aby se počítala víckrát - druhý extrém. Ne? Trochu přesnější by bylo RES-SHR+(SHR/procesů_používajících_danou_shr), pak by alespoň součet procesů pro danou shr vyšel (pokud má to teda aspoň trochu smysl :-D).
[21] Nojo, ale z těch čísel není vůbec zřejmé, která aplikace sdílí kterou paměť se kterou. Navíc se to nesdílí takhle 1:1, jak je uvedeno v tom jednoduchém příkladu. SHR je součtem celé sdílené paměti, ale jedná se o různé kousky, sdílené s různými skupinami jiných procesů. Nedá se z toho určit, kdo s kým co sdílí.
Petr Krčmář pracuje jako šéfredaktor serveru Root.cz. GNU/Linuxem a Unixem obecně se zabývá již více než deset let a věnuje se především jeho nasazení v počítačových sítích a bezpečnostní politice. Zde bloguje o Root.cz, Linuxu, internetu a světě kolem sebe.
Přečteno 112 291×
Přečteno 89 764×
Přečteno 73 160×
Přečteno 58 108×
Přečteno 54 434×