Vad är Swappiness på Linux? (och hur man ändrar det)

Linux-bytevärdet har ingenting att göra med hur mycket RAM-minne som används innan bytet startar. Det är ett allmänt rapporterat och allmänt ansett misstag. Vi förklarar vad det egentligen är.

Avbryta myter om swapiness

Byte är en teknik där data in Random Access Memory (RAM) skrivs till en speciell plats på hårddisken – antingen en växlingspartition eller en växlingsfil – för att frigöra RAM.

Linux har en inställning som kallas swappiness-värdet. Det råder mycket förvirring om vad den här inställningen styr. Den vanligaste felaktiga beskrivningen av swappiness är att den sätter ett tröskelvärde för RAM-användning, och när mängden använt RAM-minne når den tröskeln börjar bytet.

Detta är en missuppfattning som har upprepats så ofta att den nu har fått visdom. Om (nästan) alla andra säger till dig att det är precis så att byte fungerar, varför ska du tro oss när vi säger att det inte är det?

Enkel. Vi ska bevisa det.

Ditt RAM-minne är uppdelat i zoner

Linux ser inte på ditt RAM som en enda stor homogen minnespool. Den anser att den är uppdelad i ett antal olika regioner som kallas zoner. Vilka zoner som finns på din dator beror på om det är det 32-bitars eller 64-bitars. Här är en förenklad beskrivning av de möjliga zonerna på en x86-arkitektur dator.

Direct Memory Access (DMA): Detta är de låga 16 MB minne. Zonen har fått sitt namn för att det för länge sedan fanns datorer som bara kunde göra direkt minnesåtkomst till detta område av fysiskt minne.
Direct Memory Access 32: Trots sitt namn är Direct Memory Access 32 (DMA32) en zon som endast finns i 64-bitars Linux. Det är de låga 4 GB minne. Linux som körs på 32-bitars datorer kan bara göra DMA till denna mängd RAM (om de inte använder fysisk adresstillägg (PAE) kärna), vilket är hur zonen fick sitt namn. Även om det på 32-bitars datorer kallas HighMem.
Normal: På 64-bitars datorer är normalt minne allt RAM över 4 GB (ungefär). På 32-bitars maskiner är det RAM mellan 16 MB och 896 MB.
HighMem: Detta finns bara på 32-bitars Linux-datorer. Det är allt RAM över 896 MB, inklusive RAM över 4 GB på tillräckligt stora maskiner.

PAGESIZE-värdet

RAM tilldelas i sidor som har en fast storlek. Den storleken bestäms av kärnan vid uppstart genom att detektera datorns arkitektur. Normalt är sidstorleken på en Linux-dator 4 Kbyte.

Du kan se din sidstorlek med kommandot getconf:

getconf PAGESIZE

Zoner är kopplade till noder

Zoner är kopplade till noder. Noder är associerade med en central bearbetningsenhet (CPU). Kärnan kommer att försöka allokera minne för en process som körs på en CPU från noden som är associerad med den CPU:n.

Konceptet med att noder är knutna till processorer gör att blandade minnestyper kan installeras i specialiserade multi-CPU-datorer, med hjälp av Icke-uniform minnesåtkomst arkitektur.

Det är allt mycket high-end. Den genomsnittliga Linux-datorn kommer att ha en enda nod, kallad nod noll. Alla zoner kommer att tillhöra den noden. För att se noderna och zonerna i din dator, titta in i filen /proc/buddyinfo. Vi kommer att använda mindre för att göra det:

less /proc/buddyinfo

Det här är resultatet från 64-bitarsdatorn som denna artikel undersöktes på:

Node 0, zone DMA   1  1  1  0  2  1  1  0  1  1  3
Node 0, zone DMA32 2 67 58 19  8  3  3  1  1  1 17

Det finns en enda nod, nod noll. Den här datorn har bara 2 GB RAM, så det finns ingen ”normal” zon. Det finns bara två zoner, DMA och DMA32.

Varje kolumn representerar antalet tillgängliga sidor av en viss storlek. Till exempel, för DMA32-zonen, läser du från vänster:

2: Det finns 2 av 2^(0*PAGESIZE) minnesbitar.
67: Det finns 67 av 2^(1*PAGE_SIZE) minnesbitar.
58: Det finns 58 av 2^(2*PAGESIZE) minnesbitar tillgängliga.
Och så vidare, hela vägen upp till…
17: Det finns 17 av 2^(512*PAGESIZE) bitar.

Men egentligen är det enda skälet till att vi tittar på denna information för att se förhållandet mellan noder och zoner.

Arkivsidor och anonyma sidor

Minneskartläggning använder uppsättningar av sidtabellposter att registrera vilka minnessidor som används och till vad.

Minneskartläggningar kan vara:

Filstödd: Filstödda mappningar innehåller data som har lästs från en fil. Det kan vara vilken typ av fil som helst. Det viktiga att notera är att om systemet frigjorde det här minnet och behövde hämta dessa data igen, kan det läsas från filen en gång till. Men om data har ändrats i minnet måste dessa ändringar skrivas till filen på hårddisken innan minnet kan frigöras. Om det inte skedde skulle ändringarna gå förlorade.
Anonymt: Anonymt minne är en minneskartläggning utan någon fil eller enhet som backar upp det. Dessa sidor kan innehålla minne som efterfrågas av program för att lagra data, eller för sådana saker som stack och den högen. Eftersom det inte finns någon fil bakom denna typ av data måste en särskild plats avsättas för lagring av anonyma uppgifter. Den platsen är swap-partitionen eller swap-filen. Anonyma data skrivs för att byta innan anonyma sidor frigörs.
Enhetsstödd: Enheter adresseras genom blockenhetsfiler som kan behandlas som om de vore filer. Data kan läsas från dem och skrivas till dem. En enhetsstödd minnesmappning har data från en enhet lagrad i sig.
Delad: Flera sidtabellposter kan mappa till samma sida av RAM. Att komma åt minnesplatserna genom någon av mappningarna kommer att visa samma data. Olika processer kan kommunicera med varandra på ett mycket effektivt sätt genom att ändra data i dessa gemensamt övervakade minnesplatser. Delade skrivbara mappningar är ett vanligt sätt att uppnå högpresterande kommunikation mellan processer.
Copy on write: Copy on write är en lat tilldelningsteknik. Om en kopia av en resurs som redan finns i minnet efterfrågas, tillgodoses begäran genom att en mappning returneras till den ursprungliga resursen. Om en av processerna som ”delar” resursen försöker skriva till den, måste resursen verkligen replikeras i minnet för att tillåta ändringarna att göras i den nya kopian. Så minnesallokeringen sker endast på det första skrivkommandot.

För utbyte behöver vi bara bry oss om de två första i listan: filsidor och anonyma sidor.

Byte

Här är beskrivningen av swappiness från Linux-dokumentationenGitHub:

”Denna kontroll används för att definiera hur aggressiv (sic) kärnan kommer att byta minnessidor. Högre värden ökar aggressiviteten, lägre värden minskar mängden swap. Ett värde på 0 instruerar kärnan att inte initiera växling förrän mängden lediga och filstödda sidor är mindre än högvattenmärket i en zon.

Standardvärdet är 60.”

Det låter som att byte vänder byte upp eller ner i intensitet. Intressant nog sägs det att om du ställer in swappiness till noll stänger det inte av swap. Den instruerar kärnan att inte byta förrän vissa villkor är uppfyllda. Men byte kan fortfarande förekomma.

Låt oss gräva djupare. Här är definitionen och standardvärdet för vm_swappiness i kärnans källkodsfil vmscan.c:

/*
* Från 0 .. 100. Högre betyder mer swappy.
*/
int vm_swappiness = 60;

Swappiness-värdet kan variera från 0 till 100. Återigen låter kommentaren verkligen som att swappiness-värdet har betydelse för hur mycket swappis som sker, med en högre siffra som leder till mer swappiness.

Längre fram i källkodsfilen kan vi se att en ny variabel som heter swappiness tilldelas ett värde som returneras av funktionen mem_cgroup_swappiness(). Lite mer spårning genom källkoden kommer att visa att värdet som returneras av denna funktion är vm_swappiness. Så nu är variabeln swappiness inställd på det värde som vm_swappiness än var satt till.

int swappiness = mem_cgroup_swappiness(memcg);

Och lite längre ner i samma källkodsfilvi ser detta:

/*
* Med swappiness på 100 har anonym och fil samma prioritet.
* Denna skanningsprioritet är i huvudsak den omvända av IO-kostnaden.
*/
anon_prio = byte;
fil_prio = 200 – anon_prio;

Det är intressant. Två distinkta värden härleds från swappiness. Variablerna anon_prio och file_prio har dessa värden. När den ena ökar minskar den andra och vice versa.

Linux swappiness-värdet anger faktiskt förhållandet mellan två värden.

Det gyllene snittet

Filsidor innehåller data som lätt kan hämtas om det minnet frigörs. Linux kan bara läsa filen igen. Som vi har sett, om fildata har ändrats i RAM, måste dessa ändringar skrivas till filen innan filsidan kan frigöras. Men hur som helst, filsidan i RAM-minnet kan fyllas på igen genom att läsa data från filen. Så varför bry sig om att lägga till dessa sidor till swap-partitionen eller swap-filen? Om du behöver den informationen igen kan du lika gärna läsa tillbaka den från originalfilen istället för en överflödig kopia i växlingsutrymmet. Så filsidor lagras inte i swap. De ”lagras” tillbaka i originalfilen.

Med anonyma sidor finns det ingen underliggande fil kopplad till värdena i minnet. Värdena på dessa sidor har kommit fram dynamiskt. Du kan inte bara läsa in dem från en fil. Det enda sättet som anonyma sidminnesvärden kan återställas är att lagra data någonstans innan minnet frigörs. Och det är vad swap håller. Anonyma sidor som du kommer att behöva referera till igen.

Men observera att för både filsidor och anonyma sidor kan det krävas en hårddiskskrivning för att frigöra minnet. Om filsidesdata eller anonyma siddata har ändrats sedan de senast skrevs till filen eller för att byta, krävs en filsystemskrivning. För att hämta data krävs ett filsystem som läses. Båda typerna av återanvändning av sidor är kostsamma. Att försöka minska hårddiskinmatning och -utdata genom att minimera utbytet av anonyma sidor ökar bara mängden hårddiskinmatning och -utdata som krävs för att hantera filsidor som skrivs till och läses från filer.

Som du kan se från det sista kodavsnittet finns det två variabler. En kallade file_prio för ”filprioritet”, och en hette anon_prio för ”anonym prioritet”.

Variabeln anon_prio är inställd på Linux swappiness-värdet.
File_prio-värdet är satt till 200 minus anon_prio-värdet.

Dessa variabler har värden som fungerar tillsammans. Om de båda är inställda på 100 är de lika. För alla andra värden kommer anon_prio att minska från 100 till 0, och file_prio kommer att öka från 100 till 200. De två värdena matas in i en komplicerad algoritm som avgör om Linux-kärnan körs med en preferens för att återta (frigöra) filsidor eller anonyma sidor.

Du kan tänka på file_prio som systemets vilja att frigöra filsidor och anon_prio som systemets vilja att frigöra anonyma sidor. Vad dessa värden inte gör är att ställa in någon form av trigger eller tröskel för när swap ska användas. Det bestäms på annat håll.

Men när minne behöver frigöras, tas dessa två variabler – och förhållandet mellan dem – i beaktande av återvinnings- och växlingsalgoritmerna för att avgöra vilka sidtyper som helst övervägs för att frigöra. Och det avgör om den associerade hårddiskaktiviteten kommer att bearbeta filer för filsidor eller byta utrymme mot anonyma sidor.

När slår Swap verkligen in?

Vi har fastställt att Linux-bytevärdet anger en preferens för den typ av minnessidor som ska skannas för eventuell återvinning. Det är bra, men något måste avgöra när swap kommer att slå in.

Varje minneszon har ett högvattenmärke och ett lågvattenmärke. Dessa är systemhärledda värden. De är procentandelar av RAM-minnet i varje zon. Det är dessa värden som används som tröskelvärden för växlingsutlösare.

För att kontrollera vad dina hög- och lågvattenmärken är, titta in i filen /proc/zoneinfo med det här kommandot:

less /proc/zoneinfo

Var och en av zonerna kommer att ha en uppsättning minnesvärden mätt i sidor. Här är värdena för DMA32-zonen på testmaskinen. Lågvattenmärket är 13966 sidor och högvattenmärket är 16759 sidor:

Under normala driftsförhållanden, när ledigt minne i en zon faller under zonens lågvattenmärke, börjar bytesalgoritmen skanna minnessidor och leta efter minne som den kan återvinna, med hänsyn till de relativa värdena för anon_prio och file_prio.
Om Linux-bytevärdet är inställt på noll, sker swap när det kombinerade värdet av filsidor och gratissidor är mindre än högvattenmärket.

Så du kan se att du inte kan använda Linux swappiness-värdet för att påverka swappens beteende med avseende på RAM-användning. Det fungerar bara inte så.

Vad bör swapiness ställas in på?

Detta beror på hårdvara, arbetsbelastning, hårddisktyp och om din dator är en stationär dator eller en server. Uppenbarligen kommer detta inte att vara en inställning som passar alla.

Och du måste komma ihåg att swap inte bara används som en mekanism för att frigöra RAM när du får ont om minnesutrymme. Swap är en viktig del av ett välfungerande system, och utan det blir det mycket svårt för Linux att uppnå en sund minneshantering.

Att ändra Linux-bytesvärdet har en omedelbar effekt; du behöver inte starta om. Så du kan göra små justeringar och övervaka effekterna. Helst skulle du göra detta under en period av dagar, med olika typer av aktivitet på din dator, för att försöka hitta den närmaste idealiska inställningen som du kan.

Det här är några punkter att tänka på:

Att försöka ”inaktivera swap” genom att sätta Linux-swapness-värdet till noll flyttar helt enkelt den swap-associerade hårddiskaktiviteten till filassocierad hårddiskaktivitet.
Om du har åldrande, mekaniska hårddiskar, kan du försöka minska Linux-bytesvärdet för att undvika anonym återvinning av sidor och minska churn av swap-partitioner. Naturligtvis, när du sänker en inställning, ökar den andra inställningen. Att minska swap-churn kommer sannolikt att öka filsystemets churn. Men din dator kan vara gladare genom att gynna en metod framför den andra. Egentligen är det enda sättet att veta säkert att försöka se.
För engångsservrar, såsom databasservrar, kan du få vägledning från leverantörerna av databasprogramvaran. Mycket ofta har dessa applikationer sina egna specialdesignade filcache- och minneshanteringsrutiner som du skulle vara bättre att lita på. Programvaruleverantörerna kan föreslå ett Linux-bytevärde enligt maskinspecifikation och arbetsbelastning.
För den genomsnittliga stationära användaren med någorlunda ny hårdvara? Lämna det som det är.

Hur man ställer in Linux Swappiness-värdet

Innan du ändrar ditt swappiness-värde måste du veta vad dess nuvarande värde är. Om du vill minska det lite, är frågan lite mindre än vad? Du kan ta reda på det med detta kommando:

cat /proc/sys/vm/swappiness

För att konfigurera swappiness-värdet, använd sysctl kommando:

sudo sysctl vm.swappiness=45

Det nya värdet används direkt, ingen omstart krävs.

Faktum är att om du startar om, kommer swappiness-värdet att återgå till standardvärdet på 60. När du har experimenterat klart och har bestämt dig för det nya värdet du vill använda kan du göra det beständigt över omstarter genom att lägga till det i / etc/sysctl.conf fil. Du kan använda vilken editor du föredrar. Använd följande kommando för att redigera filen med nanoredigeraren:

sudo nano /etc/sysctl.conf

När nano öppnas, scrolla till botten av filen och lägg till den här raden. Vi använder 35 som permanent bytesvärde. Du bör ersätta det värde du vill använda.

vm.swappiness=35

För att spara dina ändringar och avsluta från nano, tryck på ”Ctrl+O”, tryck på ”Enter” och tryck på ”Ctrl+Z.”

Minneshantering är komplex

Minneshantering är komplicerad. Och det är därför, för den genomsnittliga användaren, det vanligtvis är bättre att lämna det till kärnan.

Det är lätt att tro att du använder mer RAM än du gör. Verktyg som topp och gratis kan ge fel intryck. Linux kommer att använda gratis RAM-minne för en mängd olika syften, såsom diskcache. Detta höjer på konstgjord väg den ”använda” minnessiffran och minskar den ”fria” minnessiffran. Faktum är att RAM-minnet som används som diskcache flaggas som både ”använt” och ”tillgängligt” eftersom det kan återvinnas när som helst, mycket snabbt.

För den oinvigde som kan se ut som att bytet inte fungerar, eller att bytesvärdet behöver ändras.

Som alltid finns djävulen i detaljen. Eller, i det här fallet, demonen. Kärnbytesdemonen.