Předpokládejme, že program požaduje trochu paměti, ale nezbývá dostatek volné paměti. Linux může reagovat několika různými způsoby. Jednou odpovědí je vybrat jinou použitou paměť, ke které se v poslední době nepřistupovalo, a přesunout tuto neaktivní paměť k výměně.
Vidím však mnoho článků a komentářů, které toto přesahují. Říká se, že i když je k dispozici velké množství volné paměti, Linux se někdy rozhodne zapsat neaktivní paměť a vyměnit ji. Zápis na swap v předstihu znamená, že až tuto paměť nakonec budeme chtít využít, nemusíme čekat na zápis na disk. Říká se, že jde o záměrnou strategii optimalizace výkonu.
mají pravdu? Nebo je to mýtus? Citujte své zdroje.
Pochopte prosím tuto otázku pomocí následujících definic:
- vyměnit
- zdarma paměť – „volná“ paměť zobrazená příkazem free. Toto je
MemFree
hodnotu z/proc/meminfo
./proc/meminfo
je virtuální textový soubor poskytovaný jádrem. Viz proc(5) nebo dokumenty RHEL. - i když je k dispozici velké množství volné paměti – pro účely argumentace si představte, že je více než 10 % volné paměti.
Odkazy
Zde jsou některé hledané výrazy:linux „oportunistické swapování“ NEBO (swap „když systém nemá nic lepšího na práci“ NEBO „když nemá nic lepšího na práci“ NEBO „když je systém nečinný“ NEBO „během nečinnosti“)
V druhém nejvyšším výsledku na Googlu se uživatel StackExchange zeptá „Proč používat swap, když je v RAM víc než dost volného místa?“ a zkopíruje výsledky free
příkaz zobrazující asi 20 % volné paměti. V reakci na tuto konkrétní otázku vidím, že tato odpověď má velký hlas:
Linux začne swapovat dříve, než se zaplní RAM. Důvodem je
zlepšení výkonu a odezvy:
Zvýší se výkon, protože někdy je lepší použít RAM pro diskovou mezipaměť než pro ukládání programové paměti. Je tedy lepší vyměnit
program, který byl nějakou dobu neaktivní, a místo toho uchovávat často používané
soubory v mezipaměti.Odezva je vylepšena odkládáním stránek, když je systém nečinný, spíše než když je paměť plná a běží nějaký program
a vyžaduje více RAM k dokončení úlohy.Swapování samozřejmě zpomaluje systém – ale alternativou k
swapování není swapování, ale více RAM nebo používání méně RAM.
První výsledek na Googlu byl označen jako duplikát výše uvedené otázky :-). V tomto případě žadatel zkopíroval podrobnosti zobrazující 7 GB MemFree
, z 16 GB. Otázka má vlastní přijatou a kladnou odpověď:
Výměna pouze v případě, že není volná paměť, je pouze případ, kdy nastavíte
swappiness
na 0. V opačném případě během nečinnosti jádro vymění paměť. Při tom nejsou data odstraněna z paměti, ale je vytvořena kopie v odkládacím oddílu.To znamená, že pokud dojde k situaci, že dojde k vyčerpání paměti, nemusí se tam a tam zapisovat na disk. V tomto případě může jádro pouze přepsat paměťové stránky, které již byly prohozeny, o kterých ví, že má kopii dat.
swappiness
parametr v podstatě pouze řídí, jak moc to dělá.
Druhá citace výslovně netvrdí, že swapovaná data jsou také uchována v paměti. Zdá se však, že byste preferovali tento přístup, pokud swapujete i v době, kdy máte 20 % volné paměti, a důvodem, proč tak činíte, je zlepšení výkonu.
Pokud vím, Linux podporuje uchovávání kopie stejných dat v hlavní paměti i odkládacím prostoru.
Také jsem si všiml běžného tvrzení, že „oportunistické swapování“ se děje „během nečinnosti“. Chápu, že mě to má ujistit, že tato funkce je obecně dobrá pro výkon. Nezahrnuji to do své výše uvedené definice, protože si myslím, že už má dost podrobností na to, aby to byla pěkná jasná otázka. Nechci to dělat složitějším, než je nutné.
Původní motivace
nahoře ukazuje `swout` (swapping), když mám gigabajty volné paměti. Proč?
Existuje několik zpráv, jako je tato, o zápisu Linuxu do swapu, když je dostatek volné paměti. Tyto zprávy by mohly vysvětlit „oportunistické swapování“. Zároveň byla navržena alespoň jedna alternativní příčina. Jako první krok při hledání možných příčin:Provádí někdy Linux „oportunistické swapování“, jak je definováno výše?
V příkladu, který jsem uvedl, je nyní otázka zodpovězena. Příčinou nebylo oportunistické swapování.
Přijatá odpověď:
Linux neprovádí „oportunistické swapování“, jak je definováno v této otázce.
Následující primární odkazy tento koncept vůbec nezmiňují:
- Pochopení správce virtuální paměti Linux. Online kniha od Mela Gormana. Napsáno v roce 2003, těsně před vydáním Linuxu 2.6.0.
- Dokumentace/admin-guide/sysctl/vm.rst. Toto je primární dokumentace laditelných nastavení správy virtuální paměti Linuxu.
Přesněji:
10.6 Démon Pageout (kswapd)
Historicky
kswapd
dříve se probouzelo každých 10 sekund, ale nyní je probouzeno pouze fyzickým alokátorem stránek, když je dosaženo počtu stránek_nízkého počtu volných stránek v zóně. […] Při extrémním tlaku na paměť budou procesy dělat prácikswapd
synchronně. […]kswapd
uvolňuje stránky, dokud není dosaženo vodoznaku pages_high.
Na základě výše uvedeného bychom neočekávali žádnou výměnu, když je počet volných stránek vyšší než „vysoký vodoznak“.
Za druhé, toto nám říká účel kswapd
je vytvořit více bezplatných stránek.
Když kswapd
zapíše paměťovou stránku k odložení, okamžitě uvolní paměťovou stránku. kswapd neuchovává kopii prohozené stránky v paměti .
Linux 2.6 používá k uvolnění stránky „rmap“. V Linuxu 2.4 byl příběh složitější. Když byla stránka sdílena více procesy, kswapd ji nedokázal okamžitě uvolnit. To je dávná historie. Všechny propojené příspěvky se týkají Linuxu 2.6 nebo vyššího.
swappiness
Tento ovládací prvek se používá k definování, jak agresivní bude jádro vyměňovat
paměťové stránky. Vyšší hodnoty zvýší agresivitu, nižší hodnoty
sníží množství swapu. Hodnota 0 dává jádru pokyn, aby
nezahájilo swap, dokud nebude dostatek volných stránek a stránek zálohovaných soubory je menší
než značka nejvyšší hladiny v zóně.
Tento citát popisuje speciální případ:pokud nakonfigurujete swappiness
hodnota bude . V tomto případě bychom navíc neměli očekávat žádnou výměnu, dokud počet stránek mezipaměti neklesne na vysoký vodoznak. Jinými slovy, jádro se pokusí zahodit téměř veškerou mezipaměť souborů, než začne swapovat. (To může způsobit masivní zpomalení. Musíte mít nějakou mezipaměť souborů! Mezipaměť souborů se používá k uložení kódu všech vašich spuštěných programů 🙂
Co jsou vodoznaky?
Výše uvedené citace vyvolávají otázku:Jak velké jsou rezervace paměti „vodoznaku“ v mém systému? Odpověď:na „malém“ systému mohou mít výchozí vodoznaky zón až 3 % paměti. Důvodem je výpočet vodoznaku „min“. Na větších systémech budou mít vodoznaky menší podíl, blíží se 0,3 % paměti.
Pokud se tedy otázka týká systému s více než 10 % volné paměti, přesné detaily této logiky vodoznaku nejsou podstatné.
Vodoznaky pro každou jednotlivou „zónu“ jsou zobrazeny v /proc/zoneinfo
, jak je zdokumentováno v proc(5). Výňatek z mého zoneinfo:
Node 0, zone DMA32
pages free 304988
min 7250
low 9062
high 10874
spanned 1044480
present 888973
managed 872457
protection: (0, 0, 4424, 4424, 4424)
...
Node 0, zone Normal
pages free 11977
min 9611
low 12013
high 14415
spanned 1173504
present 1173504
managed 1134236
protection: (0, 0, 0, 0, 0)
Aktuální „vodoznaky“ jsou min
, low
a high
. Pokud program někdy požádá o dostatek paměti ke snížení free
pod min
, program zadá „přímé vymáhání“. Program čeká, dokud jádro neuvolní paměť.
Chceme se pokud možno vyhnout přímé reklamaci. Pokud tedy free
by klesla pod low
vodoznak, jádro probudí kswapd
. kswapd
uvolňuje paměť výměnou a/nebo zrušením mezipaměti, dokud free
je nad high
znovu.
Další kvalifikace:kswapd
bude také spuštěn, aby chránil celou částku lowmem_reserve pro použití s nízkou pamětí jádra a DMA. Výchozí lowmem_reserve je asi 1/256 z prvních 4GiB RAM (zóna DMA32), takže je to obvykle kolem 16MiB.
Linux kód se odevzdá
mm:měřítko vodoznaků kswapd v poměru k paměti
[…]
watermark_scale_factor:
Tento faktor řídí agresivitu kswapd. Definuje
množství paměti zbývající v uzlu/systému, než se kswapd probudí, a
kolik paměti musí být volné, než kswapd přejde zpět do režimu spánku.Jednotka je ve zlomcích 10 000. Výchozí hodnota 10 znamená, že
vzdálenosti mezi vodoznaky jsou 0,1 % dostupné paměti v
uzlu/systému. Maximální hodnota je 1000 nebo 10 % paměti.Vysoký počet vláken, která vstupují do přímého obnovení (allocstall) nebo kswapd
předčasně uspí (kswapd_low_wmark_hit_quickly), může naznačovat,
že počet volných stránek, které kswapd udržuje z důvodů latence, je
příliš malý pro alokační shluky vyskytující se v systému. Tento knoflík
lze poté použít k odpovídajícímu vyladění agresivity kswapd.
proc:meminfo:odhadnout dostupnou paměť konzervativněji
MemAvailable
položku v/proc/meminfo
je poskytnout uživatelům nápovědu o tom, jak
množství paměti lze alokovat, aniž by došlo k odkládání, takže to vylučuje
nízké vodoznaky zón jako nedostupné pro uživatelský prostor.Pro alokaci uživatelského prostoru však
kswapd
bude skutečně získávat zpět
, dokud volné stránky nenarazí na kombinaci vysokého vodoznaku a
ochrany lowmem alokátoru stránek, která zachovává určité množství paměti DMA
a DMA32 také z uživatelského prostoru.Při výpočtu MemAvailable odečtěte celou částku, o které víme, že je pro uživatelský prostor nedostupná, od
počtu stránek zdarma.
Linuxový kód
Někdy se tvrdí, že změna swappiness
na účinně zakáže „oportunistické swapování“. To poskytuje zajímavou cestu vyšetřování. Pokud existuje něco, čemu se říká „oportunistické swapování“ a lze to vyladit pomocí swappiness, pak bychom to mohli dohnat nalezením všech řetězců volání, které čtou
vm_swappiness
. Všimněte si, že můžeme snížit náš vyhledávací prostor za předpokladu CONFIG_MEMCG
není nastaveno (tj. „paměťové cgroups“ jsou zakázány). Řetězec hovorů:
- vm_swappiness
- mem_cgroup_swappiness
- get_scan_count
- shrink_node_memcg
- zmenšit_uzel
shrink_node_memcg
je komentován „Toto je základní stránka volnější pro jednotlivé uzly. Používá jak kswapd, tak i direct reclaim“. Tj. tato funkce zvyšuje počet volných stránky. Nesnaží se duplikovat stránky k výměně, aby mohly být uvolněny mnohem později. Ale i když to slevíme:
Výše uvedený řetězec je volán ze tří různých funkcí, které jsou zobrazeny níže. Jak se dalo očekávat, můžeme call-site rozdělit na přímé reclaim v.s. kswapd. Nemělo by smysl provádět „oportunistické swapování“ v přímém zpětném získávání.
/* * This is the direct reclaim path, for page-allocating processes. We only * try to reclaim pages from zones which will satisfy the caller's allocation * request. * * If a zone is deemed to be full of pinned pages then just give it a light * scan then give up on it. */ static void shrink_zones
* kswapd shrinks a node of pages that are at or below the highest usable * zone that is currently unbalanced. * * Returns true if kswapd scanned at least the requested number of pages to * reclaim or if the lack of progress was due to pages under writeback. * This is used to determine if the scanning priority needs to be raised. */ static bool kswapd_shrink_node
* For kswapd, balance_pgdat() will reclaim pages across a node from zones * that are eligible for use by the caller until at least one zone is * balanced. * * Returns the order kswapd finished reclaiming at. * * kswapd scans the zones in the highmem->normal->dma direction. It skips * zones which have free_pages > high_wmark_pages(zone), but once a zone is * found to have free_pages <= high_wmark_pages(zone), any page in that zone * or lower is eligible for reclaim until at least one usable zone is * balanced. */ static int balance_pgdat
Pravděpodobně se tedy tvrdí, že kswapd se nějak probudí, i když jsou všechny alokace paměti okamžitě uspokojeny z volné paměti. Prohlédl jsem si použití wake_up_interruptible(&pgdat->kswapd_wait)
a nepozoruji žádná podobná probuzení.