Jun 222012
 
atemyram

Image from http://www.linuxatemyram.com/

Penso che sia un problema comune per tutti gli utenti Linux prima o poi nella loro carriera di amministratore di desktop o server “Perché Linux usa tutta la mia Ram, mentre non sta facendo molto?». A questa domanda oggi ho aggiunto un’altra domanda che è sicuramente comune a molti amministratori di sistemi Linux “Perché il comando free mi mostra la swap usata ed ho tanta Ram libera?”, Quindi dal mio studio di oggi di SwapCached vorrei presentarvi alcuni utili, o almeno lo spero, informazioni sulla gestione della memoria in un sistema Linux.


Linux ha questa regola di base: una pagina di RAM libera è RAM sprecata . La RAM viene utilizzata per molte più cose che solo i dati delle applicazioni utente. Inoltre contiene i dati per il kernel stesso e, soprattutto, è possibile eseguire una copia dei dati memorizzati sul disco per ottenere un accesso super-veloce, questo è di solito riportato come “buffer/cache”, “cache su disco” o “cached” da top . La Memoria cache è essenzialmente libera, nel senso che può essere sostituita rapidamente se un programma in funziona (o che sta partendo) richiede memoria.

Mantenere la cache significa che se qualcosa deve avere gli stessi dati ancora una volta, c’è una buona probabilità che sia ancora nella cache in memoria.

Quindi come prima cosa nel proprio sistema è possibile utilizzare il comando free per avere una prima idea di come stia andando l’utilizzo della RAM.

Questo è il risultato sul mio vecchio portatile con Xubuntu:

xubuntu-home:~# free
             total       used       free     shared    buffers     cached
Mem:          1506       1373        133          0         40        359
-/+ buffers/cache:        972        534
Swap:          486         24        462

la linea -/+ buffers/cache mostra come la memoria viene considerata usata o libera dal punto di vista delle applicazioni. In questo esempio 972 MB di Ram sono utilizzate e 534 MB sono a disposizione per le applicazioni
In generale, se po’ di swap viene utilizzata, l’uso della memoria non sta avendo impatto sulle prestazioni per nulla.

Ma se si desidera ottenere qualche informazione in più sulla vostra memoria il file che si deve guardare è /proc/meminfo, questo è il mio su Xubuntu 12,04 con un kernel 3.2.0-25-generic:

xubuntu-home:~# cat /proc/meminfo 
MemTotal:        1543148 kB
MemFree:          152928 kB
Buffers:           41776 kB
Cached:           353612 kB
SwapCached:         8880 kB
Active:           629268 kB
Inactive:         665188 kB
Active(anon):     432424 kB
Inactive(anon):   474704 kB
Active(file):     196844 kB
Inactive(file):   190484 kB
Unevictable:         160 kB
Mlocked:             160 kB
HighTotal:        662920 kB
HighFree:          20476 kB
LowTotal:         880228 kB
LowFree:          132452 kB
SwapTotal:        498684 kB
SwapFree:         470020 kB
Dirty:                44 kB
Writeback:             0 kB
AnonPages:        891472 kB
Mapped:           122284 kB
Shmem:              8060 kB
Slab:              56416 kB
SReclaimable:      44068 kB
SUnreclaim:        12348 kB
KernelStack:        3208 kB
PageTables:        10380 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     1270256 kB
Committed_AS:    2903848 kB
VmallocTotal:     122880 kB
VmallocUsed:        8116 kB
VmallocChunk:     113344 kB
HardwareCorrupted:     0 kB
AnonHugePages:         0 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       4096 kB
DirectMap4k:       98296 kB
DirectMap4M:      811008 kB

MemTotal MemFree e sono facilmente comprensibili per tutti, questi sono alcuni degli altri valori:

Cached
La cache della pagina Linux (“Copia cache” da meminfo) è il maggior consumatore singolo di RAM sulla maggior parte dei sistemi. Ogni volta che si esegue un read () da un file su disco, queste informazioni lette sono messe in memoria, e vanno nell’area di page cache. Dopo questa read () completa, il kernel ha la possibilità di gettare semplicemente la pagina via in quanto non viene utilizzata. Tuttavia, se si fa una seconda lettura della stessa area di un file, i dati verranno letti direttamente dalla memoria e nessun utilizzo del disco sarà fatto. Si tratta di un aumento di velocità incredibile ed è il motivo per cui Linux usa la cache della pagina in modo così esteso: si sta scommettendo che dopo che si accede a una pagina sul disco una sola volta, sarà fatto di nuovo l’accesso.

dentry/inode Cache
Ogni volta che si fa un ‘ls’ (o qualsiasi altra operazione: open (), stat (), ecc ..) su un filesystem, il kernel ha bisogno dei dati che sono sul disco. Il kernel analizza questi dati sul disco e li mette in alcuni strutture indipendenti dal filesystem in modo che possa essere gestito allo stesso modo in diversi filesystem . Allo stesso modo, come la cache di pagina dell’esempio, il kernel ha la possibilità di buttare via queste strutture una volta che ‘ls’ è completato. Tuttavia, fa le stessa scommessa di prima: se hai letto una volta, sei destinato a leggerlo di nuovo. Il kernel memorizza queste informazioni in diverse “Cache” chiamate dentry e cache inode. dentries sono comuni a tutti i filesystem, ma ogni filesystem ha la propria cache per gli inode.

Questa RAM è una componete di SLAB in meminfo.

È possibile visualizzare le cache diverse e le loro dimensioni eseguendo questo comando:

 head -2 /proc/slabinfo; cat /proc/slabinfo  | egrep dentry\|inode

Buffer Cache
La cache per il buffer (“Buffers:” in meminfo) è una parente stretta della cache per dentry/inode. Le dentries e gli inode in memoria rappresentano strutture su disco, ma sono disposte in modo molto diverso. Questo potrebbe essere perché abbiamo una struttura del kernel come un puntatore nella copia in memoria, ma non sul ​​disco. Potrebbe anche accadere che il formato su disco è un endianness diverso da quello della CPU.

Mappatura della memoria in top: VIRT, RES e SHR

Quando si esegue top ci sono tre campi relativi all’utilizzo della memoria. Al fine di capire le vostre esigenze di memoria sul server è necessario comprenderne il significato.

VIRT rappresenta la dimensione virtuale di un processo, che è la somma della memoria che sta effettivamente utilizzando, la memoria che ha mappato (per esempio la RAM dedicata alla scheda video per il server X), i file su disco che sono stati mappati con esso (in particolare le librerie condivise), e la memoria condivisa con altri processi. VIRT rappresenta la quantità di memoria che il programma è in grado di accedere in questo momento.

RES rappresenta la dimensione residente, che è una rappresentazione accurata della quantità di memoria fisica effettiva che un processo sta consumando. (Questo corrisponde anche direttamente alla colonna %MEM.) Questo è praticamente sempre inferiore alla dimensione VIRT, poiché la maggior parte dei programmi dipendono dalle librerie C.

SHR indica quanto della dimensione VIRT è effettivamente condivisibile (memoria o librerie). Nel caso di librerie, non significa necessariamente che l’intera libreria è residente. Ad esempio, se un programma usa solo alcune funzioni in una libreria, l’intera libreria viene mappata e sarà contata in VIRT e SHR, ma solo le parti del file di libreria contenente le funzioni utilizzate sono effettivamente caricate e sono contate in RES.

Quando si esegue top ci sono tre campi relativi all’utilizzo della memoria. Al fine di saggiare le vostre esigenze di memoria del server è necessario comprenderne il significato.

Swap

Fino ad ora abbiamo visto alcune informazioni sulla nostra RAM, ma cosa succede quando non c’è più memoria RAM libera? Se non ho memoria libera, e ho bisogno di una pagina per le pagine di cachecache inode, o cache dentry, dove posso trovarla?

Prima di tutto il kernel cerca di non lasciare che ci si avvicini a 0 byte di RAM libera. Questo perché, per liberare la RAM, di solito è necessario utilizzarne una quantità maggiore. Questo perché il nostro Kernel ha bisogno di una sorta di “spazio di lavoro” per le sue operazioni interne, e quindi se arriva a zero RAM libera non può fare niente di più.

In base alla quantità di RAM e le diverse tipologie (memoria alta/bassa ), il kernel utilizza un metodo euristico per la quantità di memoria con cui si sente a suo agio per il suo spazio di lavoro. Quando si raggiunge questa soglia, il kernel inizia a recuperare la memoria dai diversi usi sopra descritti. Il kernel può ottenere memoria da uno qualsiasi dei questi tipi.

Tuttavia, vi è un altro tipo di memoria che forse abbiamo dimenticato: i dati delle applicazioni utente.
Quando il kernel decide di non avere la memoria da una qualsiasi delle altre fonti che abbiamo descritto finora, comincia ad utilizzare la swap. Durante questo processo prende i dati delle applicazioni dell’utente e le scrive in un posto speciale (o posti) sul disco, si noti che questo accade non solo quando RAM va vicino al diventare piena, ma il kernel può decidere di passare alla swap anche alcuni dati in RAM che non sono utilizzati da qualche tempo (vedi swappiness).
Per questo motivo, anche un sistema con una grande quantità di RAM (anche se correttamente configurato) può usare la swap. Ci sono un sacco di pagine di memoria che sono i dati delle applicazioni degli utenti, ma sono raramente utilizzate. Tutte queste sono ottime candidate per essere messe in swap a favore di altri usi per la RAM.

È possibile verificare se la swap viene utilizzata con il comando free, l’ultima riga delle informazioni in uscita mostra lo spazio di swap, prendendo l’output che ho usato nell’esempio precedente:

xubuntu-home:~# free
             total       used       free     shared    buffers     cached
Mem:          1506       1373        133          0         40        359
-/+ buffers/cache:        972        534
Swap:          486         24        462

Possiamo vedere che su questo computer ci sono 24 MB di swap utilizzati e 462 MB disponibili.

Quindi la sola presenza di swap usato non è prova di un sistema che ha poca RAM per il suo carico di lavoro, il modo migliore per determinarlo è usare il comando vmstat se vedete un sacco di pagine che hanno a che fare con l’area di swap in ingresso (si, la pagina va da disco a memoria) ed in uscita (so, la pagina va da memoria a disco) vuol dire che lo swap è attivamente utilizzato e che il sistema è in “thrashing” e che si ha bisogno di nuova RAM velocemente quindi mette i dati delle applicazioni in swap, per poi prendere subito degli altri.

Quello che segue è un output sul mio computer portatile gentoo, mentre non sta facendo nulla:

~ # vmstat 5 5
procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa
 1  0      0 2802448  25856 731076    0    0    99    14  365  478  7  3 88  3
 0  0      0 2820556  25868 713388    0    0     0     9  675  906  2  2 96  0
 0  0      0 2820736  25868 713388    0    0     0     0  675  925  3  1 96  0
 2  0      0 2820388  25868 713548    0    0     0     2  671  901  3  1 96  0
 0  0      0 2820668  25868 713320    0    0     0     0  681  920  2  1 96  0

Si noti che nell’output del comando free abbiamo solo due valori per lo swap: free e used,ma c’è un altro valore importante anche per lo spazio di swap: la Swap Cached.

Swap Cached

La swap cached è molto simile nel concetto a la cache delle pagine. Una pagina di dati applicativi dell’utente scritti su disco è molto simile a una pagina di dati del file sul disco. Ogni volta che viene letta da una pagina di swap (“si” in vmstat), viene collocata nella swap cached. Proprio come la cache delle pagine, questa è una scommessa da parte del kernel. Si sta scommettendo che potremmo aver bisogno di scambiare questa pagina _ancora_ fuori. Se si verifica questa necessità, possiamo rilevare che esiste già una copia sul disco e semplicemente gettiamo la pagina via subito dalla memoria. Questo ci consente di risparmiare il costo di ri-scrivere la pagina sul disco.

La cache di swap è realmente utile solo quando stiamo leggendo i dati da swap e non li scriviamo mai. Se scriviamo sulla pagina di memoria, la copia sul disco non è più in sincronia con la copia in memoria. Se questo accade, dobbiamo scrivere sul disco per scambiare la pagina di nuovo, proprio come abbiamo fatto la prima volta. Tuttavia, il risparmio che abbiamo per qulasiasi scrittura su disco è grande, e anche con solo una piccola porzione della swap cache mai scritta, il sistema funzionerà al meglio.

Quindi, per conoscere la reale swap utilizzta dovremmo sottrarre al valore di SwapUsed il valore di SwapCached le informazioni le trovate in /proc meminfo

swappiness

Quando un’applicazione necessita di memoria e tutta la RAM è completamente occupata, il kernel ha due modi per liberare la memoria a sua disposizione: si può ridurre la cache del disco nella RAM eliminando i vecchi dati o può mandare alcune parti meno utilizzate (pagine) di programmi sulla partizione di swap su disco. Non è facile prevedere quale metodo sarà più efficace. Il kernel fa una scelta provando ad indovinare l’efficacia dei due metodi in un dato istante, sulla base della storia recente delle attività.

Prima del kernel 2.6, l’utente non aveva mezzi possibili per influenzare i calcoli e capitavano situazioni in cui il kernel spesso faceva la scelta sbagliata, che portava al thrashing ed a un rallentamento delle prestazioni. L’aggiunta di swappiness dal 2.6 ha modifiche questo comportamento.

Swappiness prende una valore compreso tra 0 e 100 per stabilire il bilanciamento tra lo swapping delle applicazioni ed il liberare la cache. A 100, il kernel preferirà sempre trovare pagine inattive e metterle in swapi; in altri casi, se un swapout si verifica dipende da quanta memoria applicazione è in uso e quanta fatica sta facendo la cache a trovare e rilasciare gli elementi inattivi.

Il valore predefinito di swappiness è 60. Un valore di 0, ottiene qualcosa di simile al vecchio comportamento in cui le applicazioni che volevano memoria potevano ridurre la cache disco ad una piccola frazione della RAM. Per i portatili che in cui si preferisce lasciare i dischi fermi, un valore di 20 o meno è raccomandato.

Conclusioni

In questo articolo ho messo alcune informazioni che ho trovato utili nel mio lavoro come amministratore di sistema spero possano essere utili anche a voi.

Riferimenti
La maggior parte di questo articolo si basa sul lavoro trovato su queste pagine:

https://en.wikipedia.org/wiki/Virtual_memory
http://www.linuxhowtos.org/System/Linux%20Memory%20Management.htm
http://linux-mm.org/Low_On_Memory

Popular Posts:

Flattr this!

  10 Responses to “Gestione della memoria in Linux”

  1. This is a great explanation of how Linux uses memory. I have often wondered why some of those numbers in Top were so high but never took time to research. Thanks for putting this together. I think I can go further reading the subject now with more background than before and a better understanding of the topic.

  2. Thanks for writing this article, and for detailing it in such plain wording. I’ve become addicted to having Conky on all my desktops and the memory numbers they display have always been something of mystery to me. Usually when I’ll have a lot of things going on the numbers just didn’t add up, even more so when swap was involved. Things make a lot more sense now.

  3. Thanks great explanation

  4. can anyone tell me the meaning of following
    Active(anon): 432424 kB
    Inactive(anon): 474704 kB
    Active(file): 196844 kB
    Inactive(file): 190484 kB

  5. Innanzitutto grazie mille per l’articolo, ho notato che il mio pc accumula poco alla volta tutta la memoria, appena svuoto la cache si libera tutta. Chiudo tutto ma poco alla volta viene tutta la memoria anche se svuoto la cache questa poco alla volta viene tutta occupata quindi devo sempre svuotarla. Sai se è normale? Non vorrei essere vittima di una minaccia che succhia memoria D:

  6. Really nice article.. Thanks a lot for this!

  7. Hey there! Great article ! thanks for sharing ..

  8. Very Good.

  9. Thanks for this amazing article. keep it up

  10. Excellent read. Thanks for sharing. Keep it up

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

(required)

(required)

*