Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Si applica a: ✔️ macchine virtuali di Linux
Questo articolo illustra come risolvere i problemi di prestazioni della memoria che si verificano in macchine virtuali Linux in Microsoft Azure.
Il primo passaggio per lavorare sui problemi relativi alla memoria consiste nel valutare gli elementi seguenti:
- Modalità di utilizzo della memoria da parte delle applicazioni ospitate nel sistema
- Livello appropriato di memoria disponibile nel sistema
È possibile iniziare analizzando i modelli di carico di lavoro per determinare se il sistema è configurato correttamente. Successivamente, potrebbe essere necessario valutare la possibilità di ridimensionare la macchina virtuale o di scegliere tra un'architettura NUMA (Accesso non uniforme alla memoria) e l'architettura UMA (Uniform Memory Access). Inoltre, è utile considerare se le prestazioni dell'applicazione potrebbero trarre vantaggio da Transparent HugePages (THP). L'approccio migliore consiste nel collaborare con il fornitore dell'applicazione per comprendere i requisiti di memoria consigliati.
Aree chiave interessate dalla memoria
Allocazione di memoria del processo : la memoria è una risorsa necessaria per ogni processo, incluso il kernel. La quantità di memoria necessaria dipende dalla progettazione e dallo scopo del processo. La memoria è solitamente assegnata allo stack o all'heap. Ad esempio, i database in memoria, ad esempio SAP HANA, si basano principalmente sulla memoria per archiviare ed elaborare i dati in modo efficiente.
Utilizzo cache pagine: la memoria può anche essere utilizzata indirettamente tramite un aumento della cache delle pagine. La cache delle pagine è una rappresentazione in memoria di un file letto in precedenza da un disco. Questa cache consente di evitare letture su disco ripetute. L'esempio migliore di questo processo è un file server che trae vantaggio da questa funzionalità del kernel sottostante.
Architettura della memoria : è importante sapere quali applicazioni o applicazioni sono in esecuzione nella stessa macchina virtuale e se potrebbero competere per la memoria disponibile. Potrebbe anche essere necessario verificare se la macchina virtuale è configurata per l'uso dell'architettura NUMA o UMA. A seconda dei requisiti di memoria di un processo, l'architettura UMA potrebbe essere preferibile in modo che la RAM completa possa essere risolta senza penalità. D'altra parte, per HPC (High Performance Computing) che coinvolge molti processi o processi di piccole dimensioni che rientrano in uno dei nodi NUMA, è possibile trarre vantaggio dalla località della cache della CPU.
Sovrallocazione della memoria - È anche importante determinare se il kernel consente la sovrallocazione della memoria. A seconda della configurazione, ogni richiesta di memoria viene soddisfatta fino a quando l'importo richiesto non è più disponibile.
Scambia spazio L'abilitazione dello scambio migliora la stabilità complessiva del sistema fornendo un buffer durante condizioni di memoria insufficiente. Questo buffer aiuta il sistema a rimanere resiliente sotto pressione. Per altre informazioni, vedere questo articolo sul kernel Linux.
Informazioni sugli strumenti per la risoluzione dei problemi relativi alla memoria
Per risolvere i problemi, è possibile usare gli strumenti da riga di comando seguenti.
gratuito
Per visualizzare la quantità di memoria disponibile e usata in un sistema, usare il free
comando .
Screenshot dell'output gratuito di esempio.
Questo comando genera un riepilogo della memoria riservata e disponibile, incluso lo spazio di scambio totale e usato.
pidstat e vmstat
Per una visualizzazione più dettagliata dell'utilizzo della memoria da parte dei singoli processi, usare il pidstat -r
comando .
Quando si analizzano i report sull'utilizzo della memoria, due colonne importanti da osservare sono VSZ
e RSS
:
- VSZ (Virtual Set Size) mostra la quantità totale di memoria virtuale (in kilobyte) riservata da un processo.
- RSS (Resident Set Size) indica la quantità di memoria virtuale attualmente contenuta nella RAM (ad esempio, memoria di cui è stato eseguito il commit).
Un'altra metrica utile è majflt/s
(il numero di errori di pagina principali al secondo). Questo numero misura la frequenza con cui una pagina di memoria deve essere letta da un dispositivo di scambio. In caso di dubbi sull'utilizzo elevato della memoria di scambio, verificare la quantità utilizzando lo strumento vmstat
per monitorare nel tempo le statistiche di page-in e page-out.
Esempio di output di vmstat
In questo esempio è possibile osservare che molte pagine di memoria vengono lette o scritte per lo scambio. Questi valori elevati indicano in genere che il sistema sta esaurendo la memoria disponibile. Questa condizione può verificarsi perché più processi sono in competizione per la memoria o perché la maggior parte delle applicazioni non può usare la memoria disponibile.
Un motivo comune per cui la memoria non disponibile è l'uso di HugePages. HugePages sono memoria riservata. Non tutte le applicazioni possono usare memoria riservata. In alcune situazioni, potrebbe essere necessario valutare se le applicazioni necessitano di HugePages o funzionano in modo più efficace usando Transparent HugePages (THP). THP consente al kernel di gestire in modo dinamico pagine di memoria di grandi dimensioni. Ad esempio, la macchina virtuale Java (JVM) può sfruttare il THP abilitando il flag seguente:
-XX:+UseTransparentHugePages
Per altre informazioni su THP, vedere Transparent HugePage Support.
Per altre informazioni su HugePages, vedere HugeTLB Pages.For more information about HugePages, see HugeTLB Pages.
Test dell'utilizzo THP in un programma di esempio
Per osservare come il THP viene usato dal sistema, è possibile eseguire un piccolo programma C che alloca circa 256 MB di RAM. Il programma usa la madvise
chiamata di sistema per indicare al kernel Linux che questa area di memoria deve usare pagine enormi se il THP è supportato.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>
#define LARGE_MEMORY_SIZE (256 * 1024 * 1024) // 256MB
int main() {
char str[2];
// Allocate a large memory area
void *addr = mmap(NULL, LARGE_MEMORY_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (addr == MAP_FAILED) {
perror("mmap");
return 1;
}
// Use madvise to give advice about the memory usage
if (madvise(addr, LARGE_MEMORY_SIZE, MADV_HUGEPAGE) != 0) {
perror("madvise");
munmap(addr, LARGE_MEMORY_SIZE);
return 1;
}
// Initialize the memory
int *array = (int *)addr;
for (int i = 0; i < LARGE_MEMORY_SIZE / sizeof(int); i++) {
array[i] = i;
}
memset(addr, 0, LARGE_MEMORY_SIZE);
printf("Press Enter to continue\n");
fgets(str,2,stdin);
// Clean up
if (munmap(addr, LARGE_MEMORY_SIZE) == -1) {
perror("munmap");
return 1;
}
return 0;
}
Se si esegue il programma, non è direttamente osservabile se THP viene usato dal programma.
È possibile verificare l'utilizzo THP complessivo nel sistema esaminando il /proc/meminfo
file. Controllare il AnonHugePages
campo per determinare la quantità di memoria che usa THP. Questo file fornisce solo statistiche a livello di sistema.
Per sapere se un processo usa THP, è necessario esaminare il smaps
file nella /proc
directory del processo in questione. Ad esempio, in /proc/2275/smaps
cercare una riga contenente la parola heap
(mostrata qui all'estrema destra).
Questo esempio mostra che un segmento di memoria di grandi dimensioni è stato allocato e contrassegnato come THPeligible
(THP sono in uso). Usando madvice syscall
, l'allocazione di questo blocco di memoria è molto più efficiente. È possibile ottenere la stessa efficienza usando Huge Pages. A seconda delle dimensioni dell'allocazione, il kernel potrebbe assegnare pagine standard di 4 KB o blocchi contigui più grandi. Questa ottimizzazione può migliorare le prestazioni per le applicazioni a elevato utilizzo di memoria.
Per altre informazioni, vedere Transparent Hugepage Support.
NUMA
Se le applicazioni sono in esecuzione in un sistema NUMA con più nodi, è importante conoscere la capacità di memoria di ogni nodo. Tutti i nodi possono accedere alla memoria totale del sistema. Tuttavia, si ottengono prestazioni ottimali se i processi eseguiti in un particolare nodo NUMA operano sulla memoria sotto controllo diretto di tale nodo. Se il nodo locale non può soddisfare una richiesta di memoria, il sistema alloca memoria da un altro nodo. Tuttavia, l'accesso alla memoria tra i nodi introduce la latenza e può causare penalità per le prestazioni. È pertanto necessario monitorare la località della memoria per assicurarsi che i carichi di lavoro siano allineati alle risorse di memoria dei nodi NUMA assegnati.
Lo screenshot seguente mostra un esempio della configurazione NUMA del sistema.
Questa configurazione mostra che l'accesso alla memoria all'interno dello stesso nodo ha un livello di distanza pari a 10. Se si vuole accedere alla memoria Node 1
da Node 0
, questo processo ha un valore di distanza elevato pari a 12 ma è comunque gestibile. Tuttavia, se si vuole accedere alla memoria da NODE 3
NODE 0
, il livello di distanza diventa 32. Questo processo è ancora fattibile, ma è anche tre volte più lento. È utile considerare queste differenze quando si diagnosticano problemi di prestazioni o si ottimizzano i carichi di lavoro associati alla memoria. Per altre informazioni, vedere questo articolo sul kernel Linux. Per una descrizione dello numactl
strumento, vedere numactl(8).
Per determinare se esiste un riallineamento dei processi e sarebbe necessario un nodo diverso, usare lo numastat
strumento . La documentazione per questo strumento è disponibile in numastat(8). Lo migratepages
strumento migratepages(8) consente di spostare le pagine di memoria nel nodo corretto.
Overcommitment e killer OOM
L'overcommitment è una scelta di progettazione importante che può influire seriamente sulle prestazioni e sulla stabilità del sistema. Il kernel Linux supporta tre modalità:
- 'Euristico'
- 'Impegnati sempre oltre il possibile'
- Non prendere troppi impegni
Per impostazione predefinita, il sistema usa lo Heuristic
schema . Questa modalità offre un compromesso bilanciato tra consentire sempre l'overcommit della memoria e negarlo rigorosamente. Per altre informazioni, vedere la documentazione del kernel.
Un'impostazione overcommitment non corretta potrebbe impedire alle pagine di memoria di allocare memoria. Potenzialmente, questa condizione potrebbe ostacolare la creazione di nuovi processi o impedire alle strutture del kernel interno di acquisire memoria sufficiente.
Se si verifica che il problema sia correlato all'allocazione di memoria, la causa più probabile di questo problema è che non ci sono risorse sufficienti per il kernel. In questo tipo di situazione, l'assassino dell'OOM (Out-Of-Memory) potrebbe essere richiamato. Il suo processo consiste nel liberare alcune pagine di memoria da usare dalle attività del kernel o da altre applicazioni. Richiamando l'assassino OOM, il sistema avvisa che ha raggiunto i limiti delle risorse. Se è possibile eliminare la possibilità di una perdita di memoria, la causa di questa condizione potrebbe essere che troppi processi sono in esecuzione o che i processi che consumano molta memoria. Per risolvere il problema, prendere in considerazione l'aumento delle dimensioni della macchina virtuale o lo spostamento di alcune applicazioni in un altro server.
Log di sistema generati durante gli eventi OOM
Questa sezione presenta una tecnica per identificare il momento in cui viene attivato OOM Killer e per scoprire quali informazioni vengono registrate dal sistema.
Il semplice programma C seguente verifica la quantità di memoria che può essere allocata dinamicamente in un sistema prima che non riesca.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ONEGB (1 << 30)
int main() {
int count = 0;
while (1) {
int *p = malloc(ONEGB);
if (p == NULL) {
printf("malloc refused after %d GB\n", count);
return 0;
}
memset(p,1,ONEGB);
printf("got %d GB\n", ++count);
}
}
Questo programma indica che l'allocazione di memoria ha esito negativo dopo circa 3 GB.
Quando il sistema esaurisce la memoria, viene richiamato l'assassino OOM. È possibile visualizzare i log correlati usando il dmesg
comando . Le voci di log iniziano in genere come illustrato nello screenshot seguente.
In genere, le voci si concludono con un riepilogo dello stato della memoria.
Tra queste voci è possibile trovare informazioni dettagliate sull'utilizzo della memoria e sul processo selezionato per la terminazione.
Da queste informazioni è possibile estrarre le informazioni dettagliate seguenti:
4194160 kBytes physical memory
No swap space
3829648 kBytes are in use
Nell'esempio di log seguente, il processo malloc ha richiesto una singola pagina di 4 KB (order=0). Anche se la pagina di 4 KB è piccola, il sistema era già sotto pressione. Il log mostra che la memoria è stata allocata dalla "Zona normale".
La memoria disponibile (free
) è di 29.500 KB. Tuttavia, la filigrana minima (min
) è 34.628 KB. Poiché il sistema è al di sotto di questa soglia, solo il kernel può usare la memoria rimanente e le applicazioni spazio utente vengono negate. L'assassino OOM viene richiamato a questo punto. Seleziona il processo con l'utilizzo più elevato oom_score
e di memoria ('RSS'). In questo esempio il processo malloc aveva un oom_score
valore pari a 0, ma ha anche il valore più alto RSS
(917760). Viene quindi selezionato come obiettivo per l'eliminazione.
Monitorare la crescita graduale della memoria
Gli eventi OOM sono facili da rilevare perché i messaggi correlati vengono registrati nella console e nei log di sistema. Tuttavia, gli aumenti graduali dell'utilizzo della memoria che non causano un evento OOM possono essere più difficili da rilevare.
Per monitorare l'utilizzo della memoria nel tempo, usare lo sar
strumento del sysstat
pacchetto. Per concentrarsi sui dettagli della memoria, usare l'opzione "r", ad esempio "sar -r".
Output di esempio
In questo caso, l'utilizzo della memoria aumenta per circa due ore. Poi, torna al quattro per cento. Questo comportamento potrebbe essere previsto, ad esempio durante le ore di accesso di punta o le attività di creazione di report a elevato utilizzo di risorse. Per determinare se questo comportamento è normale, potrebbe essere necessario monitorare l'utilizzo in diversi giorni e quindi correlarlo con l'attività dell'applicazione. L'utilizzo elevato della memoria non è necessariamente un problema. Dipende dal carico di lavoro e dal modo in cui le applicazioni sono progettate per l'uso della memoria.
Per individuare i processi che utilizzano la maggior parte della memoria, usare pidstat
.
Output di esempio
Questo output visualizza tutti i processi in esecuzione e le relative statistiche. Un altro approccio consiste nell'usare lo strumento "ps" per ottenere risultati simili: ps aux --sort=-rss | head -n 10
Output di esempio
Perché ordinare per RSS?
Resident Set Size (RSS) è la parte della memoria di processo contenuta nella RAM (memoria fisica non scambiata). Al contrario, la dimensione del set virtuale (VSZ) rappresenta la quantità totale di memoria riservata dal processo, inclusa la memoria non sottoposta a commit.
Committed memory
fa riferimento a pagine effettivamente scritte nella memoria fisica. Se si sta provando a identificare i processi che utilizzano la maggior quantità di memoria fisica (inclusa la memoria di swap), concentrarsi sulla colonna RSS
. Nell'output di esempio il snapd
processo sembra usare molta memoria, ma il valore RSS
è basso. Il malloc
processo ha valori simili VSZ
e RSS
che indicano che usa attivamente più di 1,3 GB di memoria.
Clausola di esclusione di responsabilità per il contatto di terze parti
Microsoft fornisce informazioni di contatto di terze parti per aiutarti a trovare ulteriori informazioni su questo argomento. Queste informazioni di contatto sono soggette a modifica senza preavviso. Microsoft non garantisce l'accuratezza delle informazioni di contatto di terze parti.
Contattaci per ricevere assistenza
Per domande o richieste di assistenza, creare una richiesta di supporto o chiedere supporto alla community di Azure. È anche possibile inviare commenti e suggerimenti sul prodotto alla community di commenti e suggerimenti di Azure.