Hva er Swappiness på Linux? (og hvordan endre det)

Linux-bytteverdien har ingenting å gjøre med hvor mye RAM som brukes før bytte starter. Det er en mye rapportert og allment antatt feil. Vi forklarer hva det egentlig er.

Avbryte myter om swapiness

Bytte er en teknikk hvor data inn Random Access Memory (RAM) skrives til en spesiell plassering på harddisken – enten en swap-partisjon eller en swap-fil – for å frigjøre RAM.

Linux har en innstilling som kalles swappiness-verdien. Det er mye forvirring om hva denne innstillingen kontrollerer. Den vanligste feilbeskrivelsen av swappiness er at den setter en terskel for RAM-bruk, og når mengden brukt RAM treffer den terskelen, starter swapping.

Dette er en misforståelse som har blitt gjentatt så ofte at den nå er mottatt visdom. Hvis (nesten) alle andre forteller deg at det er akkurat slik byttehandel fungerer, hvorfor skal du tro oss når vi sier at det ikke er det?

Enkel. Vi skal bevise det.

RAM-minnet ditt er delt inn i soner

Linux tenker ikke på RAM-en din som en stor homogen lagringsplass. Den anser det for å være delt inn i en rekke forskjellige regioner kalt soner. Hvilke soner som finnes på datamaskinen din, avhenger av om det er det 32-bit eller 64-bit. Her er en forenklet beskrivelse av mulige soner på en x86-arkitektur datamaskin.

Direkte minnetilgang (DMA): Dette er de lave 16 MB minne. Sonen har fått navnet sitt fordi det for lenge siden var datamaskiner som bare kunne gjøre direkte minnetilgang til dette området av fysisk minne.
Direct Memory Access 32: Til tross for navnet er Direct Memory Access 32 (DMA32) en sone som kun finnes i 64-bit Linux. Det er de lave 4 GB minne. Linux som kjører på 32-bits datamaskiner kan bare gjøre DMA til denne mengden RAM (med mindre de bruker fysisk adresseutvidelse (PAE) kjerne), som er hvordan sonen fikk navnet sitt. Selv om det på 32-bits datamaskiner kalles HighMem.
Normal: På 64-biters datamaskiner er normal minne all RAM over 4 GB (omtrent). På 32-bits maskiner er det RAM mellom 16 MB og 896 MB.
HighMem: Dette finnes bare på 32-bits Linux-datamaskiner. Det er alt RAM over 896 MB, inkludert RAM over 4 GB på tilstrekkelig store maskiner.

PAGESIZE-verdien

RAM er tildelt i sider, som har en fast størrelse. Denne størrelsen bestemmes av kjernen ved oppstart ved å oppdage arkitekturen til datamaskinen. Vanligvis er sidestørrelsen på en Linux-datamaskin 4 Kbyte.

Du kan se sidestørrelsen din ved å bruke getconf-kommandoen:

getconf PAGESIZE

Soner er knyttet til noder

Soner er festet til noder. Noder er knyttet til en sentral prosesseringsenhet (CPU). Kjernen vil prøve å allokere minne for en prosess som kjører på en CPU fra noden som er knyttet til den CPU.

Konseptet med at noder er knyttet til CPUer gjør at blandede minnetyper kan installeres i spesialiserte multi-CPU-datamaskiner, ved å bruke Ikke-uniform minnetilgang arkitektur.

Det hele er veldig avansert. Den gjennomsnittlige Linux-datamaskinen vil ha en enkelt node, kalt node null. Alle soner vil tilhøre den noden. For å se nodene og sonene på datamaskinen din, se i /proc/buddyinfo-filen. Vi bruker mindre for å gjøre det:

less /proc/buddyinfo

Dette er utdataene fra 64-bits datamaskinen denne artikkelen ble undersøkt 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 er en enkelt node, node null. Denne datamaskinen har bare 2 GB RAM, så det er ingen «normal» sone. Det er bare to soner, DMA og DMA32.

Hver kolonne representerer antall tilgjengelige sider av en viss størrelse. For eksempel, for DMA32-sonen, les fra venstre:

  Hvordan spille Cities Skylines på Linux

2: Det er 2 av 2^(0*PAGESIZE) minnebiter.
67: Det er 67 av 2^(1*PAGE_SIZE) minnebiter.
58: Det er 58 av 2^(2*PAGESIZE) minnebiter tilgjengelig.
Og så videre, helt opp til…
17: Det er 17 av 2^(512*PAGESIZE) biter.

Men egentlig er den eneste grunnen til at vi ser på denne informasjonen for å se forholdet mellom noder og soner.

Filsider og anonyme sider

Minnekartlegging bruker sett med sidetabelloppføringer å registrere hvilke minnesider som brukes, og til hva.

Minnetilordninger kan være:

Filstøttet: Filstøttede tilordninger inneholder data som er lest fra en fil. Det kan være hvilken som helst filtype. Det som er viktig å merke seg er at hvis systemet frigjorde dette minnet og trengte å skaffe disse dataene igjen, kan det leses fra filen igjen. Men hvis dataene har blitt endret i minnet, må disse endringene skrives til filen på harddisken før minnet kan frigjøres. Hvis det ikke skjedde, ville endringene gå tapt.
Anonym: Anonymt minne er en minnekartlegging uten fil eller enhet som støtter det. Disse sidene kan inneholde minne forespurt av programmer for å holde data, eller for slike ting som stable og haug. Fordi det ikke er noen fil bak denne typen data, må det settes av en spesiell plass for lagring av anonyme data. Det stedet er swap-partisjonen eller swap-filen. Anonyme data er skrevet for å bytte før anonyme sider frigjøres.
Enhetsstøttet: Enheter adresseres gjennom blokkeringsenhetsfiler som kan behandles som om de var filer. Data kan leses fra dem og skrives til dem. En enhetsstøttet minnekartlegging har data fra en enhet lagret i seg.
Delt: Flere sidetabelloppføringer kan kartlegge til samme side av RAM. Å få tilgang til minneplasseringene gjennom noen av tilordningene vil vise de samme dataene. Ulike prosesser kan kommunisere med hverandre på en svært effektiv måte ved å endre dataene i disse felles overvåkede minnestedene. Delte skrivbare kartlegginger er et vanlig middel for å oppnå høyytelses kommunikasjon mellom prosesser.
Kopier på skriv: Kopier på skriv er en lat tildelingsteknikk. Hvis det etterspørres en kopi av en ressurs som allerede er i minnet, tilfredsstilles forespørselen ved å returnere en tilordning til den opprinnelige ressursen. Hvis en av prosessene som «deler» ressursen prøver å skrive til den, må ressursen virkelig replikeres i minnet for å tillate endringene i den nye kopien. Så minneallokeringen finner kun sted på den første skrivekommandoen.

For bytteforhold trenger vi bare å bekymre oss om de to første på listen: filsider og anonyme sider.

Bytte

Her er beskrivelsen av bytte fra Linux-dokumentasjonenGitHub:

«Denne kontrollen brukes til å definere hvor aggressiv (sic) kjernen vil bytte minnesider. Høyere verdier vil øke aggressiviteten, lavere verdier reduserer mengden bytte. En verdi på 0 instruerer kjernen om ikke å starte swap før mengden av gratis og filstøttede sider er mindre enn høyvannsmerket i en sone.

Standardverdien er 60.»

Det høres ut som om byttet svinger opp eller ned i intensitet. Interessant nok sier den at å sette byttet til null ikke slår av bytte. Den instruerer kjernen om ikke å bytte før visse betingelser er oppfylt. Men bytte kan fortsatt forekomme.

La oss grave dypere. Her er definisjonen og standardverdien til vm_swappiness i kjernekildekodefilen vmscan.c:

/*
* Fra 0 .. 100. Høyere betyr mer byttet.
*/
int vm_swappiness = 60;

Swappiness-verdien kan variere fra 0 til 100. Igjen, kommentaren høres absolutt ut som om swappiness-verdien har betydning for hvor mye bytte som foregår, med et høyere tall som fører til mer bytte.

Videre i kildekodefilen kan vi se at en ny variabel kalt swappiness er tildelt en verdi som returneres av funksjonen mem_cgroup_swappiness(). Noe mer sporing gjennom kildekoden vil vise at verdien som returneres av denne funksjonen er vm_swappiness. Så nå er variabelen swappiness satt til å være lik den verdien vm_swappiness ble satt til.

int swappiness = mem_cgroup_swappiness(memcg);

Og litt lenger ned i samme kildekodefilser vi dette:

  Hvordan spille Max Payne på Linux

/*
* Med bytte på 100 har anonym og fil samme prioritet.
* Denne skanneprioriteten er i hovedsak den omvendte av IO-kostnaden.
*/
anon_prio = bytte;
file_prio = 200 – anon_prio;

Det er interessant. To distinkte verdier er avledet fra swappiness. Variablene anon_prio og file_prio har disse verdiene. Når den ene øker, minker den andre, og omvendt.

Linux-bytteverdien setter faktisk forholdet mellom to verdier.

Det gylne snitt

Filsider inneholder data som enkelt kan hentes hvis minnet er frigjort. Linux kan bare lese filen igjen. Som vi har sett, hvis fildataene har blitt endret i RAM, må disse endringene skrives til filen før filsiden kan frigjøres. Men uansett kan filsiden i RAM fylles på nytt ved å lese data fra filen. Så hvorfor bry deg med å legge disse sidene til swap-partisjonen eller swap-filen? Hvis du trenger disse dataene igjen, kan du like godt lese dem tilbake fra den opprinnelige filen i stedet for en overflødig kopi i bytteplassen. Så filsider lagres ikke i swap. De er «lagret» tilbake i den opprinnelige filen.

Med anonyme sider er det ingen underliggende fil knyttet til verdiene i minnet. Verdiene på disse sidene er dynamisk kommet frem til. Du kan ikke bare lese dem inn igjen fra en fil. Den eneste måten anonyme sideminneverdier kan gjenopprettes på er å lagre dataene et sted før du frigjør minnet. Og det er det bytte holder. Anonyme sider som du må referere igjen.

Men merk at for både filsider og anonyme sider, kan frigjøring av minne kreve en harddiskskriving. Hvis filsidedataene eller de anonyme sidedataene har endret seg siden de sist ble skrevet til filen eller for å bytte, er en filsystemskriving nødvendig. For å hente dataene vil det kreve at du leser et filsystem. Begge typer sidegjenvinning er kostbare. Å prøve å redusere harddiskinngang og -utgang ved å minimere bytte av anonyme sider øker bare mengden harddiskinndata og -utdata som kreves for å håndtere filsider som skrives til og leses fra filer.

Som du kan se fra den siste kodebiten, er det to variabler. En kalte file_prio for «filprioritet», og en kalte anon_prio for «anonym prioritet».

Variabelen anon_prio er satt til Linux-bytteverdien.
File_prio-verdien er satt til 200 minus anon_prio-verdien.

Disse variablene har verdier som fungerer sammen. Hvis de begge er satt til 100, er de like. For alle andre verdier vil anon_prio reduseres fra 100 mot 0, og file_prio vil øke fra 100 mot 200. De to verdiene inngår i en komplisert algoritme som bestemmer om Linux-kjernen kjører med en preferanse for å gjenvinne (frigjøre) filsider eller anonyme sider.

Du kan tenke på file_prio som systemets vilje til å frigjøre filsider og anon_prio som systemets vilje til å frigjøre anonyme sider. Det disse verdiene ikke gjør er å sette noen form for trigger eller terskel for når swap skal brukes. Det er bestemt et annet sted.

Men når minne må frigjøres, tas disse to variablene – og forholdet mellom dem – i betraktning av gjenvinnings- og byttealgoritmene for å bestemme hvilke sidetyper som fortrinnsvis vurderes for frigjøring. Og det dikterer om den tilknyttede harddiskaktiviteten skal behandle filer for filsider eller bytte plass for anonyme sider.

Når slår Swap faktisk inn?

Vi har slått fast at Linux-bytteverdien angir en preferanse for typen minnesider som skal skannes for potensiell gjenvinning. Det er greit, men noe må avgjøre når swap skal slå inn.

Hver minnesone har et høyvannsmerke og et lavvannsmerke. Dette er systemavledede verdier. De er prosenter av RAM i hver sone. Det er disse verdiene som brukes som utløserterskler for bytte.

For å sjekke hva dine høye og lave vannmerker er, se inne i /proc/zoneinfo-filen med denne kommandoen:

less /proc/zoneinfo

Hver av sonene vil ha et sett med minneverdier målt i sider. Her er verdiene for DMA32-sonen på testmaskinen. Lavvannsmerket er 13966 sider, og høyvannsmerket er 16759 sider:

  Hvordan spille Baldur's Gate 3 på Linux

Under normale driftsforhold, når ledig minne i en sone faller under sonens lavvannsmerke, begynner swap-algoritmen å skanne minnesider på jakt etter minne som den kan gjenvinne, og tar hensyn til de relative verdiene til anon_prio og file_prio.
Hvis Linux-bytteverdien er satt til null, skjer swap når den kombinerte verdien av filsider og gratissider er mindre enn høyvannsmerket.

Så du kan se at du ikke kan bruke Linux-bytteverdien til å påvirke bytteoppførselen med hensyn til RAM-bruk. Det fungerer bare ikke sånn.

Hva bør swapiness settes til?

Dette avhenger av maskinvare, arbeidsmengde, harddisktype og om datamaskinen din er en stasjonær eller server. Det er klart at dette ikke kommer til å være en størrelse som passer alle typer innstilling.

Og du må huske på at swap ikke bare brukes som en mekanisme for å frigjøre RAM når du går tom for minneplass. Swap er en viktig del av et velfungerende system, og uten det blir fornuftig minneadministrasjon svært vanskelig for Linux å oppnå.

Å endre Linux-bytteverdien har en umiddelbar effekt; du trenger ikke å starte på nytt. Så du kan gjøre små justeringer og overvåke effektene. Ideelt sett vil du gjøre dette over en periode på dager, med forskjellige typer aktivitet på datamaskinen din, for å prøve å finne den nærmeste ideell innstillingen du kan.

Dette er noen punkter du bør vurdere:

Hvis du prøver å «deaktivere swap» ved å sette Linux-bytteverdien til null, skifter du ganske enkelt den swap-assosierte harddiskaktiviteten til filassosiert harddiskaktivitet.
Hvis du har aldrende, mekaniske harddisker, kan du prøve å redusere Linux-bytteverdien for å skjemme bort fra anonym sidegjenvinning og redusere churn av byttepartisjon. Selvfølgelig, når du skrur ned én innstilling, øker den andre innstillingen. Å redusere swap-churn vil sannsynligvis øke filsystem-churn. Men datamaskinen din kan være lykkeligere ved å favorisere den ene metoden fremfor den andre. Den eneste måten å vite sikkert på er å prøve og se.
For enkeltbruksservere, for eksempel databaseservere, kan du få veiledning fra leverandørene av databaseprogramvaren. Svært ofte har disse applikasjonene sine egne spesialdesignede filbuffer- og minnebehandlingsrutiner som det er bedre å stole på. Programvareleverandørene kan foreslå en Linux-bytteverdi i henhold til maskinspesifikasjoner og arbeidsmengde.
For den gjennomsnittlige stasjonære brukeren med rimelig fersk maskinvare? La det være som det er.

Hvordan stille inn Linux Swappiness-verdien

Før du endrer bytteverdien din, må du vite hva dens nåværende verdi er. Hvis du vil redusere det litt, er spørsmålet litt mindre enn hva? Du kan finne ut med denne kommandoen:

cat /proc/sys/vm/swappiness

For å konfigurere bytteverdien, bruk sysctl-kommandoen:

sudo sysctl vm.swappiness=45

Den nye verdien brukes umiddelbart, ingen omstart er nødvendig.

Faktisk, hvis du starter på nytt, vil swappiness-verdien gå tilbake til standardverdien på 60. Når du er ferdig med å eksperimentere og har bestemt deg for den nye verdien du vil bruke, kan du gjøre den vedvarende over omstart ved å legge den til / etc/sysctl.conf-fil. Du kan bruke hvilken editor du foretrekker. Bruk følgende kommando for å redigere filen med nano-editoren:

sudo nano /etc/sysctl.conf

Når nano åpnes, bla til bunnen av filen og legg til denne linjen. Vi bruker 35 som permanent bytteverdi. Du bør erstatte verdien du ønsker å bruke.

vm.swappiness=35

For å lagre endringene og gå ut av nano, trykk «Ctrl+O», trykk «Enter» og trykk «Ctrl+Z.»

Minnehåndtering er kompleks

Minnehåndtering er komplisert. Og det er derfor, for den gjennomsnittlige brukeren, er det vanligvis bedre å overlate det til kjernen.

Det er lett å tro at du bruker mer RAM enn du gjør. Verktøy som topp og gratis kan gi feil inntrykk. Linux vil bruke gratis RAM til en rekke egne formål, for eksempel diskbufring. Dette hever kunstig det «brukte» minnet og reduserer det «frie» minnetallet. Faktisk er RAM-en som brukes som diskbuffer flagget som både «brukt» og «tilgjengelig» fordi den kan gjenvinnes når som helst, veldig raskt.

For de uinnvidde kan det se ut som om bytte ikke fungerer, eller at bytteverdien må endres.

Som alltid er djevelen i detaljene. Eller, i dette tilfellet, demonen. Kjernebyttedemonen.