Koliko poznajemo operacijski sustav : Memory Management

Memory management

Memory management je proces upravljanja memorijom na nivou operacijskog sustava. Njegova osnovna zadaća je osigurati mogućnost dinamičkog alociranja memorije, na zahtjev programa (procesa odnosno aplikacije) ali i osloboditi memoriju koja više nije potrebna, u trenutku kada nije potrebna. Ova zadaća je vrlo važna i to dodatno s obzirom na činjenicu da su svi današnji Linuxi, kao i drugi operacijski sustavi u kojima više programa/procesa/aplikacija radi u isto vrijeme.

 

Memory management koristi nekoliko metoda da bi povećao efikasnost korištenja memorije.

 

Sustav virtualne memorije

Upotreba tkzv. virtualne memorije je metoda koja se koristi za odvajanje virtualnih memorijskih adresa koje koriste procesi, od stvarnih memorijskih adresa RAM memorije. Ova metoda omogućava odvajanje procesa u smislu korištenja posebnog memorijskog adresnog prostora te efikasnijeg korištenja RAM memorije, pomoću metode koja se zove “Paging”.

 

Osim toga “Memory management” može koristiti i “Swapping” na disk, prema potrebi.

I na kraju, kvaliteta memorijskog managera ima znatan utjecaj na performanse cijelog sustava.

 

Virtualna memorija

Korištenje Virtualne memorije odvaja korištenje fizičke memorije i od same aplikacije odnosno

procesa. Dakle aplikacije koriste virtualni adresni prostor i to na način da kada aplikacija treba

pristupiti memoriji, zahtjev za memorijskom adresom se translatira (pretvara) iz virtualnog adresnog prostora u fizički adresni proctor RAM memorije.

 

Ovo znači da vaš program nikada ne koristi “stvarne” memorijske adrese (tj. adrese fizičke RAM

memorije), niti ima pristup do njih. Umjesto toga svaki program dobiva virtualne memorijske adrese koje koristi.

Memorijske adrese su zapravo pokazivači na memorijske lokacije na kojima se nalazi naš program.

Kada program treba nešto zapisati ili čitati u memoriju ili iz memorije, on mora provjeriti s koje memorijske adrese će čitati koji dio podataka.

O točnom načinu čitanja i zapisivanja čemo kasnije kada budemo pričali o “Paging”-u.

 

Upotrebom virtualne memorije, operativni sustav ima potpunu kontrolu nad fizičkom memorijom odnosno nad njenim pristupom. Samim time operacijski sustav može limitirati način na koji procesi (aplikacije) pristupaju memoriji.

Ta kontrola se zove “Memory protection” i ona ograničava pristup svakog procesa, na dio memorije koji je alociran samo za njega te mu onemogućava ulazak u adresni prostor nekog drugog procesa (aplikacije). Implikacije ovoga su vrlo jasne : onemogućavanje malicioznih namjernih ili nenamjernih radnji.

Iako svaki proces (aplikacija) radi unutar svog ograničenog adresnog prostora u memoriji, često je potrebno dijeljenje određenog adresnog prostora memorije između više aplikacija. Primjerice potreban  je pristup podacima koji se dijele između procesa (aplikacija).

 

Klasičan primjer su neke biblioteke, kojima treba pristupati veći broj procesa odnosno aplikacija istovremeno. Ova metoda se zove “Shared Memory”.

Istovremeno “Shared Memory” je najbrža metoda za komunikaciju između procesa (aplikacija).

 

Ovo se postiže klasifikacijom pristupa memoriji na tkzv. “Primary Storage” i “Secondary Storage”. Jedan od zadataka “Memory Manager”-a je i baratanje s ove dvije vrste pristupa memoriji, na nivou svakog procesa.

 

Dakle adresni prostor koji vidi proces (aplikacija), aplikaciji izgleda kao kontinuirani adresni prostor, koji se sastoji od više dijelova ili segmenata.

 

Translacija Virtualnih adresa u fizičke se događa unutar procesora (CPU) i to unutar dijela koji se zove “Memory Management Unit” (MMU).

 

Slika prikazuje način mapiranja virtualne memorije u fizičku memoriju:

linux_-_ram-new.jpg

Paging

Prije nego se uveo “Paging”, operacijski sustav je morao ubaciti cijeli proces (aplikaciju) u RAM memoriju, popunivši ju u kontinuiranom slijedu. S obzirom da se ista stvar morala raditi za svaki proces (program), svaki od njih je zauzeo memoriju u konituiranom nizu.

Problem je nastajao kada bi se neki proces (aplikacija) ugasio, te bi na tom mjestu ostala “prazna” memorija i ta fragmentacija bi se sve više povećavala, gašenjem i podizanjem novih procesa (aplikacija) i uzrokovala probleme.

 

Kao što smo spomenuli, virtualna memorija je podjeljena na segmente odnosno tkzv. stranice (engl.Pages) odnosno blokove virtualnog adresnog prostora.

Ovi blokovi su uglavnom veličine 4kB.

 

Dakle sva raspoloživa memorija je “razlomljena” u blokove od 4kB.

Slično kao što je površina tvrdog diska, razlomljena u sektore, koji su najmanje jedinice za zapis podataka na tvrdi disk.

 

Paging i dijeljenje memorije (Shared Memory)

Dijeljenje memorije (engl. Sharing) koje smo također spominjali, se nadzire od strane “Memory managera”.

 

Svaki proces (aplikacija) u memoriji podjeljen je u blokove (Pages) i to na način da je izvršni dio programa u jednom dijelu a dio koji sadrži podatke u drugom dijelu memorije.

 

Memorija se djeli tako da se unutar tkzv. tablice blokova (engl. Page Table) za različite procese,

pokazuje na iste stranice (Page) koje su dijeljene između njih.

 

Kako to radi

Korištenjem modela dijeljenja memorije, više nema potrebe za dupliciranjem zauzeća memorije. Osim toga na ovaj način procesi (aplikacije) lakše mogu dijeliti podatke. Dio memory management zadužen za dijeljenje memorije se zove “IPC System” (Inter Process Communication).

 

Pojednostavljeno više procesa (aplikacija) dijeli dio memorije, koji se koristi za njihovu međusobnu komunikaciju.

Ti dijelovi memorije, zbog toga što se dijele između procesa, moraju imati kontrolu : tko im može

pristupiti a tko ne može.

Za to je potreban mehanizam zaključavanja pristupa (engl. Locking)  tom (svakom) dijelu memorije.

Ovdje se uključuju tkzv semafori (engl. Semaphores), a oni su zapravo jednostavne

zastavice (engl. Flags).

 

Semafori odnosno zastavice rade tako da ako se određeni dio dijeljene memorije trenutno koristi od strane nekog procesa (aplikacije), tada se podiže zastavica i drugi procesi (aplikacije) koje bi u istom trenutku željele pristupiti toj istoj memoriji (na toj istoj adresi), moraju malo pričekati, sve dok se semafor za pristup ne isključi.

 

Naredba u Linuxu koja barata s “IPC System” (Inter Process Communication) je ipcs.

 

Veličina odnosno količina RAM memorije koja se može koristiti kao “Shared Memory”, je definirana za cijeli operacijski sustav ali se može i povećavati ili smanjivati.

Njena veličina je definirana brojem blokova (standardneveličine 4KB)

 

Postoje dva limita na veličinu dijeljene memorije:

  1. SHMMAX je maksimalna veličina jednog (bilo kojeg) segmenta dijeljene memorije
  2. SHMALL je zbroj svih segmenata dijeljene memorije za cijeli operacijski sustav.

 

 

Kako provjeriti ove vrijednosti ?.

Provjera veličine bloka – ovo je “Page size” (obično je 4096 byte tj. 4KB):

 

sysctl kernel.shmmni


kernel.shmmni = 4096

 

Provjera SHMMAX:

 

sysctl kernel.shmmax

kernel.shmmax = 68719476736

 

Provjera SHMALL:

 

sysctl kernel.shmall

kernel.shmall = 4294967296

 

Uloga “Page Table”-a

“Page Table” ili tablica memorijskih stranica odnosno blokova je strukturirana tablica u kojoj se nalaze sva mapiranja između virtualnih i fizičkih memorijskih adresa.

U operacijskim sustavima, koji koriste virtualnu memoriju (a to su svi moderni OS-ovi) svaki proces vidi svoju memoriju koju koristi kao kontinuiranu. Zapravo je ta memorija raspoređena po fizičkoj RAM memoriji i eventualno se još nalazi dijelom na “Swap” particiji tvrdog diska.

Kada proces (aplikacija) traži pristup memoriji, u nadležnosti je operacijskog sustava, da pogleda u “Page Table” tablicu te napravi povezivanje odnosno mapiranje virtualne memorijske adrese i fizičke memorijske adrese te dohvati tražene podatke (u konačnici pročita ili snimi [“read” ili “write” ] nešto u ili iz memorije).

Svaki unos u tablici : Virtualna adresa ↔ Fizička adresa se zove “Page table entry” (PTE).

 

Proces translacije adresa

“Memory Managemet Unit” (MMU) procesora (engl. CPU) pohranjuje (engl. Cache) unose iz “Page” tablice koji su nedavno korišteni, u svoju internu (vrlo malu) memoriju odnosno svoj međuspremnik (engl. Buffer). Ovaj međuspremnik se zove “Translation Lookaside Buffer” (TLB).

Kada se virtualna adresa treba translatirati u fizičku, prvo se provjerava TLB. Ako je unos pronađen i fizička adresa je poznata, nastavlja se s pristupom memoriji.

Ako traženi unos ne postoji u TLB memoriji (ovo je tkzv. “TLB miss”), nastavlja se s čitanjem originalne “Page” tablice i traži se potreban unos (ovo se zove “Page walk”). Kada se unos pronađe on se odmah i upisuje u TLB memoriju te se ponovno pokreće proces čitanja iz TLB memorije. Potom se standardno nastavlja s pristupom fizičkoj memoriji tj. točnoj adresi u njoj, gdje se nalaze traženi podaci.

Ovo je proces koji se stalno ponavlja, s obzirom da u TLB memoriju modernih procesora (CPU) stane tek nekoliko stotina unosa.

Moramo biti svjesni da, što se više memorije alocira i dodjeli procesima (aplikacijama), “Page table” sve više i više raste. S obzirom je da “Page size” samo 4KB, to praktično znači da je za svakih alociranih 1GB RAM memorije, potrebna Page tablica, sa 262144 unosa, koji se stalno pretražuju i oni zadnji korišteni se stavljaju u TLB međuspremnik, kako je gore objašnjeno.

Dakle ako imate 8GB RAM koji su potpuno iskorišteni to znači da će “Page” tablica narasti na 2 097 152 unosa. Ovo unosi znatne probleme, kod aplikacija koje koriste veću količinu RAM memorije, jer za svaki pristup svakoj pojedinoj memorijskoj lokaciji slijedi proces od gor. Dakle pretraživanje stotine tisuća ili mlijuna unosa, za svako čitanje ili pisanje po svakoj pojedinoj lokaciji memorije (veličine 4KB).

 

Koliki je TLB modernih procesora

Za primjerice Intel “Nehalem” mikroarhitekturu odnosno generaciju CPU-a, stanje po pitanju TLB-a je slijedeće.

Ova generacija procesora ima dvo razinski TLB: manji L1 (ITLB1 i DTLB1) koji je i najbrži te potom veći L2 (DTLB1 ), koji je i malo sporiji.

Koje su njihove veličine odnosno kapacitet ?

  1.       L1 (DTLB1): 64 unosa za “Page” veličine 4KB (standardna veličina) i 32 unosa za Page veličine 2 ili 4 MB (o ovim veličinama u naprednom dijelu)

  2.      L1 (ITLB1): 128 unosa za “Page” veličine 4KB (standardna veličina) i 14 unosa za Page veličine 2 ili 4 MB (o ovim veličinama u naprednom dijelu)

  3.     L2 (DTLB) : 512 unosa za “Page” veličine 4KB (standardna veličina)

 

Pogledajmo sada procesor : Intel “Core 2 Duo E7500”, sa dvije fizičke jezgre :

 

Sada pogledajmo i noviji poslužiteljski procesor “Xeon” i to model “E5-2650 V.3”.

Slika prikazuje sustav sa 128GB RAM, od kojih 64GB pripada prvom fizičkom procesoru a 64GB drugom:

 

Ova logička shema je dobivena s naredbom:

lstopo –whole-system –no-io

 

Vidljivo je da prvi fizički procesor (Socket P#0) ima fizičkih 10 jezgri (P#0 do P#12) a unutar svake od njih se nalaze po dvije logičke jezgre (to su “Hyper Threading” jezgre), oznaka PU P# “BROJ jezgre”.

Istu konfiguraciju ima i drugi fizički procesor. Naime ovo je poslužiteljska matična poloča koja ima dva procesora Intel Xeon E-2650 v.3. sa ukupno 40 jezgri (20 na prvom a 20 na drugom fizičkom procesoru).

 

Vratimo se na TLB

Slika prikazuje proces dohvaćanja podataka iz Page tablice i TLB memorije:

Naučili smo kako se pronalaze i dohvaćaju  unosi ali dobro je znati i da se proces koji slijedi kod TLB promašaja (engl. TLB miss) može odraditi na dva načina :

  1.    Hardverski – korištenjem registara procesora (CPU) CR3 registar na x86 arhitekturi] – CPU odrađuje pretraživanje, ostalo Operacijski sustav
  2.    Softverski – Operacijski sustav odrađuje sve (od popunjavanja TLB-a, pretraživanja (page walk) i sl).

Prosječne performanse TLB-a su:

  • Vrijeme dohvata unosa : 0.5 – 1 takt procesora (engl. clock cycle)
  • Promašaj : 10 – 100 taktova procesora (engl. clock cycles)
  • Prosječni postotak promašaja 0.01 -1 %

 

Osnovna računica ako je vrijeme dohvata 1 takt, a promašaj 30 taktova te postotak promašaja 1% , tada je potrebno 1.3 taktova procesora za dohvaćanje jednog unosa u TLB tablici.

 

Zbog čega toliko priče o TLB-u ?

Kao što smo rekli operacijski sustav istovremeno obrađuje više procesa u pozadini. To “istovremeno” baš i nije potpuno točno.

Naime jedan procesor, odnosno u novijim arhitekturama se to odnosi na jednu jezgru procesora (engl. CPU Core), u bilo kojoj jedinici vremena, u stanju je obrađivati samo jedan tok informacija odnosno jedan proces ili nit (engl. Thread), potom se prebaciti na drugi, pa na prvi , i tako dalje  ovo prebacivanje se zove “Context Switching”.

Ovo je zapravo ono što zovemo “Multitasking” ili “višezadaćnost” odnosno privid da jedan procesor može obrađivati više zadataka (engl. Tasks).

Kod ovog prebacivanja između procesa, TLB tablica se u većini slučajeva mora potpuno isprazniti (engl. TLB Flush), pošto je vrlo vjerojatno da će većina ako ne i gotovo svi unosi u tablici biti nevažeći. Nevažeči zbog toga jer je TLB prilično malog kapaciteta, a svaki proces koristi druge djelove memorije, pa prema tome mapiranja koja su ostala u TLB memoriji pokazuju na translacije (virtualna memorija – fizička memorija )za adrese koje novi proces ne koristi – on je u nekom drugom opsegu memorijskih adresa.

 

Svako novo prebacivanje između procesa odnosno “Context Switch”, prazni TLB memoriju, te ju ponovno popunjava pretraživanjem “glavne” “Page” tablice. S obzirom da se svake sekunde dešava ogroman broj ovih prebacivanja, jasno je koliko ovo može utjecati a i utiče na performanse cijelog sustava.

 

Ovo nije jedini problem koji uzrokuje “Context switching”, isto tako se uz pražnjenje TLB-a, briše i večina registara procesora, koji se moraju ponovno popuniti kod svake nove promjene procesa koji je trenutno aktivan.

 

Zbog čega toliko priče o “Page Table”-u

Pogledajmo poslužitelj sa 128 GB RAM, od koje je u upotrebi večina, odnosno oko 127 GB.

Filtrirati ćemo sve iz statistike upotrebe RAM memorije /proc/meminfo što je vezano za pojam “Page”

 

cat /proc/meminfo | grep Page

AnonPages:        47143856 
kBPageTables:       109852 
kBAnonHugePages:         0 
kBHugePages_Total:       0
HugePages_Free:          0
HugePages_Rsvd:          0
HugePages_Surp:          0
Hugepagesize:         2048 kB

Prva stvar koja je vidljiva je ta da je “Page” tablica narasla na 107 MB (109852 kB) što znači da se u tablici nalazi oko 28 049 408 (28 milijuna 49 tisuća i 408 unosa)  – za 4kB stranice.

Ovdje se koristi standardna veličina stranice (page) od 4KB.

Sjetimo se : problem je u tome što se kod svakog pristupa RAM memoriji, koja je za naše aplikacije, razlomljena u komadiće od 4KB, potrebno svaki puta pogledati u “Page Table” tablicu , pronači (jednu po jednu) memorijsu lokaciju od 4KB te nakon toga i doći do nje.

Zamislimo da vaša aplikacija treba nešto upisati ili čitati u 40MB RAM memorije koja je zapravo razlomljena u blokove od 4KB, što znači da je potrebno čitanje 10000 unosa u tablici da bi se došlo do svih memorijskih lokacija s kojih treba čitati ili u koje treba nešto upisati.

U primjeru gore s relativno velikom količinom RAM memorije u upotrebi stvari postaju još gore.

Riješenje je upotreba tkzv “Huge Pages” odnosno prelazak s 4KB blokova na puno veće blokove (za x86 je tu o pravilu 2MB), s ovom metodom , smanjili smo broj unosa u tablicu i samim time broj pregledavanja i dohvaćanja unosa u “Page” tablicu, poprilično, točnije 512 puta.

I naravno uvijek postoji problem – ovo nije moguće napraviti za cijeli sustav već samo za točno određeni dio memorije.

I još malo komplikacije, “Huge Pages” neće raditi sam od sebe, već vaša aplikacija tj. programski jezik u kojem ste ju napisali, mora podržavati ovakan način rada.

Dobra strana je to što večina ozbiljnijih apikacija zna koristiti “Huge Pages”, potrebno je “samo” sve znati konfigurirati, što ponekad (zapravo često) nije jednostavno.

 

 

 

 

Ovaj članak je samo dio priče o RAM memoriji, koja se nalazi u  knjizi “Uvod u Linux”.

 

Ako vas zanima malo više, pogledajte poglavlje o RAM memoriji :

https://www.opensource-osijek.org/dokuwiki/wiki:knjige:uvod_u_linux#ram_memorija

Hrvoje Horvat avatar
Hrvoje Horvat
Hrvoje Horvat mrežni je i sistem inženjer s dugogodišnjim (18+ g.) iskustvom u razvoju, testiranju i implementaciji, od najmanjih do enterprise kategorije IT sustava. Njegova područja rada su od mrežnih protokola do mrežnih servisa, preko standardne mrežne opreme do specijaliziranih komponenti i sustava, preko raznih mrežnih elemenata i sustava za mrežnu pohranu i dijeljenje podataka te platformi za Virtualizaciju, do protokola i sustava za redundanciju te sustava visoke dostupnosti (HA).