A Server di paging della memoria può perdere significativamente tempo di risposta e throughput sotto carico se troppe pagine si spostano dalla RAM allo swap. In questo articolo vi mostrerò le cause, i valori misurati e le regolazioni specifiche che posso apportare per rallentare il paging e aumentare sensibilmente le prestazioni del server.
Punti centrali
Per fornire un orientamento chiaro, riassumerò brevemente i messaggi chiave e vi mostrerò dove si trovano i tipici colli di bottiglia e come risolverli. Le alte velocità di paging costano molto Prestazioni, perché gli accessi al supporto dati sono molto più lenti della RAM. Valori misurati come MByte disponibili, Byte acceduti e Pagine/Secondo mi forniscono valori affidabili. Segnali per un imminente thrashing. La virtualizzazione esacerba gli effetti dello swapping attraverso il ballooning e lo swap dell'hypervisor quando gli host sono sovraccarichi. Riduco gli errori di pagina con aggiornamenti della RAM, THP/pagine enormi, messa a punto di NUMA e modelli di allocazione puliti. Il monitoraggio regolare mantiene I rischi e rende calcolabili i picchi di carico.
- Swap vs. RAMNanosecondi in RAM contro micro/millisecondi su supporti dati
- BattituraPiù trasferimenti di pagine che lavoro utile, le latenze esplodono
- Frammentazione: Le allocazioni di grandi dimensioni falliscono nonostante la memoria „libera“.
- IndicatoriMByte disponibili, Byte accessibili, Pagine/Sec.
- SintonizzazioneTHP/Pagine enormi, vm.min_free_kbytes, NUMA, RAM
Come funziona la paginazione sui server
Separo la memoria virtuale e quella fisica in pagine fisse, in genere 4 KB, che è la MMU tramite tabelle di pagine. Se la RAM scarseggia, il sistema operativo sposta le pagine inattive nelle aree di swap o di scambio. Ogni errore di pagina costringe il kernel a recuperare i dati dal supporto dati e costa preziosa RAM. Tempo. Le pagine di grandi dimensioni, come le Transparent Huge Pages (THP), riducono l'impegno amministrativo e minimizzano le miss del TLB. Per i principianti, vale la pena di dare un'occhiata a memoria virtuale, per comprendere meglio le relazioni tra processi, frame di pagina e swap.
Swap vs. RAM: latenze e thrashing
La RAM risponde in nanosecondi, mentre le unità SSD/HDD rispondono in micro-millisecondi e sono quindi ordini di grandezza più veloci. più lento sono. Se il carico supera la memoria fisica di lavoro, il tasso di paging aumenta e la CPU attende l'I/O. Questo effetto può facilmente portare al thrashing, in cui si spende più tempo per lo swapping che per il lavoro produttivo. Questo effetto può facilmente portare al thrashing, in cui si spende più tempo nello swapping che nel lavoro produttivo. Lavoro si perde. Soprattutto con l'utilizzo di 80-90%, l'interattività e le sessioni remote si deteriorano. Controllo il Utilizzo dello swap e tracciare i confini prima che il sistema si ribalti.
Indicatori e valori soglia
I valori misurati in modo pulito prendono le decisioni RAM e la messa a punto. Su Windows faccio attenzione ai MByte disponibili, ai Byte cessed, alle Pagine/Secondo e ai byte pagati/non pagati del pool. Su Linux, controllo vmstat, free, sar, ps meminfo e dmesg per verificare la presenza di eventi fuori memoria. L'aumento dei problemi di pagina e la diminuzione dei MByte liberi indicano l'imminenza di colli di bottiglia. Pianifico le soglie critiche in modo conservativo, in modo da poter evitare i picchi di carico senza Furto con scasso intercettazione.
| Indicatore di prestazione | Sano | Avviso | Critico |
|---|---|---|---|
| \Memory\Pool byte pagati / byte non pagati | 0-50% | 60-80% | 80-100% |
| MByte disponibili | >10% o 4 GB | <10% | <1% o <500 MB |
| % Byte salvati | 0-50% | 60-80% | 80-100% |
Linux: Swappiness, Zswap/ZRAM e parametri di writeback
Oltre a THP/Huge Pages, ho ridotto sensibilmente il paging controllando l'aggressività dello swapping e del writeback. vm.swappiness controlla quanto presto il kernel spinge le pagine nello swap. Sui server con molta RAM, di solito uso 1-10, in modo che la cache delle pagine rimanga grande e gli heap inattivi non migrino prematuramente. Su sistemi molto scarsi, un valore leggermente più alto può salvare l'interattività, perché la cache non si esaurisce del tutto - il fattore decisivo è la misurazione sotto carico reale.
Con Zswap (swap compresso nella RAM), riduco la pressione di I/O se ci sono molte pagine fredde per un breve periodo. Questo costa cicli di CPU, ma spesso è più economico dell'I/O a blocchi. Per i sistemi edge o di laboratorio, a volte uso ZRAM come swap primario per rendere più robusti gli host di piccole dimensioni; lo uso in modo mirato in produzione quando è disponibile spazio per la CPU.
Controllo i percorsi di scrittura tramite vm.dirty_*-parametri. Invece di valori percentuali, preferisco lavorare con byte assoluti per evitare tempeste di writeback con grandi capacità di RAM. Il lavaggio in background inizia abbastanza presto, mentre byte_sporchi stabilisce dei limiti massimi rigidi per i carichi di lavoro pigri. Valori di esempio che uso come punto di partenza:
swapping limitato #
sysctl -w vm.swappiness=10
# Controllare il writeback (byte invece che per cento)
sysctl -w vm.dirty_background_bytes=67108864 # 64 MB
sysctl -w vm.dirty_bytes=268435456 # 256 MB
# Non scartare la cache VFS in modo troppo aggressivo
sysctl -w vm.vfs_cache_pressure=50
All'indirizzo Scambio di design Preferisco i dispositivi NVMe veloci e imposto le priorità in modo che il kernel utilizzi prima lo swap più veloce. Un dispositivo di swap dedicato impedisce la frammentazione dei file di swap.
# Controllare le priorità di swap
swapon --show
# Attivare lo swap sul dispositivo veloce con priorità alta
swapon -p 100 /dev/nvme0n1p3
Importante: osservo il guasti maggiori/minori e la profondità della coda di I/O in parallelo: questo è l'unico modo per capire se lo swappiness ridotto o Zswap stiano attenuando i picchi di latenza effettivi.
Cause dell'elevata frequenza di paging
Se non c'è una memoria di lavoro fisica, i byte di accesso aumentano attraverso la memoria integrata. RAM e il sistema passa allo swap. La memoria frammentata rende difficile l'allocazione di grandi quantità, per cui le applicazioni si bloccano nonostante la RAM „libera“. Query scadenti o indici mancanti gonfiano inutilmente gli accessi ai dati e aumentano i carichi di lavoro. I picchi di carico dovuti a backup, implementazioni, ETL o cron job concentrano i requisiti di memoria in brevi finestre temporali. Le macchine virtuali sono sottoposte a un'ulteriore pressione quando gli host superano il limite della RAM ed eseguono segretamente gli swap dell'hypervisor. Attivare.
Virtualizzazione, ballooning e overcommitment
Negli ambienti virtualizzati, l'hypervisor nasconde la situazione reale della RAM e si affida al ballooning e allo swapping all'interno del sistema. Ospiti. Se l'host incontra dei colli di bottiglia, le macchine virtuali perdono prestazioni allo stesso tempo, anche se ognuna è „verde“ a sé stante. La paginazione intelligente durante l'avvio nasconde gli avvii a freddo, ma sposta i costi sulla pipeline I/O. Controllo le metriche di host e guest insieme e riduco l'overcommitment prima che gli utenti se ne accorgano. I dettagli sull'effetto dell'overcommit sono illustrati nella sezione dedicata a Sovraccarico di memoria, in modo che la pianificazione della capacità rimanga resiliente.
Container e Kubernetes: cgroups, limiti e sfratti
I contenitori spostano i limiti di memoria dalla macchina virtuale alla macchina cgroups. Il fattore decisivo è che richieste e limiti sono impostati in modo realistico: I limiti troppo stretti causano uccisioni precoci fuori memoria, le richieste troppo generose peggiorano l'utilizzo e fingono riserve. Mantengo gli heap di JVM/Node/.NET coerentemente vincolati ai limiti del contenitore (ad esempio, l'euristica della percentuale), in modo che il GC di runtime non si scontri con il cgroup.
In Kubernetes, faccio attenzione alle classi di QoS (Guaranteed, Burstable, BestEffort) e Soglie di sfratto a livello di nodo. Sotto la pressione della memoria, Kubelet favorisce i pod BestEffort: se si vogliono mantenere gli SLO, è necessario assegnare un budget adeguato alle risorse. PSI (Pressure Stall Information) rende visibile la pressione cgroup-local; utilizzo questi segnali per scalare o riprogrammare i pod in modo proattivo. Per i carichi di lavoro con pagine di grandi dimensioni, definisco richieste esplicite di HugePage per pod, in modo che lo scheduler selezioni i nodi adatti.
Strategie di ottimizzazione: Hardware e sistema operativo
Comincerò con la vite di aggiustamento più sobria: più RAM spesso elimina immediatamente le latenze maggiori. In parallelo, riduco gli errori di pagina tramite THP in modalità „on“ o „madvise“, se i profili di latenza lo consentono. Le pagine enormi riservate forniscono prevedibilità ai motori in-memory, ma richiedono una precisa pianificazione della capacità. Con vm.min_free_kbytes creo riserve ragionevoli per far fronte ai picchi di allocazione senza compensare la compattazione. Gli aggiornamenti del firmware e del kernel eliminano gli errori di contorno, la gestione della memoria e NUMA-equilibrio.
| Impostazione | Obiettivo | Benefici | Suggerimento |
|---|---|---|---|
| vm.min_free_kbytes | Riserva per picchi di allocazione | Meno OOM/compattazione | 5-10% della RAM |
| THP (su/consigliato) | Utilizzare pagine più grandi | Meno frammentazione | Osservare le latenze |
| Pagine enormi | Blocchi continui | Assegnazioni prevedibili | Capacità di riserva stabile |
Database e carichi di lavoro in hosting
I database soffrono rapidamente quando la cache del buffer si restringe e le query vengono eseguite a causa dello swap in I/O annegare. Un'impostazione della memoria massima fortemente limitata protegge SQL/NoSQL dallo spostamento reciproco con la cache del file system. Indici, sargabilità e strategie di join personalizzate riducono i carichi di lavoro e quindi la pressione sulla RAM. Nelle configurazioni di hosting, pianifico gli indici di ricerca, le cache e i worker PHP FPM nei momenti di picco, in modo che i profili di carico non si scontrino. Il monitoraggio dell'aspettativa di vita del buffer e delle pagine mi avverte tempestivamente di Tendenza al ribasso.
Pratica: piano di misura e programma di messa a punto
Inizio con una linea di base di 24-72 ore, in modo da rendere visibili gli schemi e i lavori quotidiani. diventare. Quindi imposto un profilo target per la memoria RAM libera, le pagine accettabili al secondo e i tempi di attesa I/O massimi. Quindi apporto le modifiche in modo incrementale: prima i limiti, poi THP/pagine enormi, infine la capacità. Misuro ogni modifica su almeno un ciclo di carico utilizzando la stessa metodologia. Pianifico in anticipo le cancellazioni e le decostruzioni in modo da poter reagire rapidamente in caso di effetti negativi. per reindirizzare.
Test di carico riproducibili e previsioni di capacità
Per prendere decisioni affidabili, riproduco i set di lavoro tipici: Cache calde/fredde, finestre batch, picchi di login/checkout. Utilizzo strumenti sintetici (ad esempio stress-ng per i percorsi di memoria, fio per l'I/O e benchmark memcached/Redis per i tipi di cache) per simulare in modo specifico la pressione sulla memoria. Eseguo i test in tre varianti per ogni caso: solo app, app+co-runner (backup, scansione AV), app+picchi di I/O. Questo mi permette di riconoscere le interferenze che rimangono nascoste nei test di sola app.
Raccolgo pannelli di metriche identici (memoria, PSI, attesa I/O, furto di CPU/ready, guasti) per ogni modifica. Un rollout canarino con traffico 5-10% scopre i rischi in una fase iniziale, prima di distribuire la configurazione su larga scala. Per quanto riguarda la capacità, pianifico con i set di lavoro del caso peggiore più la riserva, non con le medie smussate.
Risoluzione dei problemi: strumenti e firme
Su Linux, vmstat, sar, iostat, perf e strace mi forniscono le informazioni più importanti. Note per i page fault, i tempi di attesa e gli heap. Per quanto riguarda Windows, mi affido a Performance Monitor, Resource Monitor e alle tracce di ETW. Messaggi come „compaction stalls“, „kswapd high CPU“ o OOM kills indicano gravi colli di bottiglia. L'interattività fluttuante, le lunghe pause GC e l'aumento delle pagine sporche confermano il sospetto. Uso i dump dell'heap e i profilatori di memoria per trovare le perdite e i problemi inappropriati. Assegnazioni.
Pratica specifica di Windows: Pagefile, Working Set e pool di pagine
Sui server Windows, mi assicuro che una dimensione sufficientemente File di scambio su unità SSD veloci ed evitare le configurazioni „no pagefile“. Le dimensioni minime fisse evitano che il sistema si restringa e si riduca inaspettatamente nei momenti di picco. Distribuisco i file di pagina su più volumi, se necessario, e osservo Guasti gravi/sec e l'utilizzo dei pool pagati/non pagati.
Per i servizi ad alta intensità di memoria, attivo in modo specifico Blocco delle pagine in memoria (ad esempio per i server SQL) in modo che il kernel non spinga i carichi di lavoro fuori dall'insieme di lavoro. Allo stesso tempo, limito in modo netto le cache delle applicazioni per evitare che il sistema si prosciughi in altri modi. Identifico le perdite di driver o di pool con PoolMon/RAMMap; in caso di guasti, un taglio controllato dell'elenco di standby aiuta a ripristinare l'interattività a breve termine - solo come diagnosi, non come soluzione permanente.
Importanti anche i piani di risparmio energetico impostati su „prestazioni massime“, i driver e il firmware di NIC/storage aggiornati. Le stranezze dello scheduler o i driver dei filtri non aggiornati sorprendentemente portano spesso a picchi di memoria e di I/O, che potrei interpretare erroneamente come una pura carenza di RAM.
Utilizzate saggiamente THP, NUMA e le dimensioni delle pagine
Le Transparent Huge Pages riducono la pressione TLB, ma le promozioni sporadiche possono causare picchi di latenza. produrre. Per i carichi di lavoro con SLO rigorosi, quindi, mi affido spesso a „madvise“ o a pagine enormi fisse. Il bilanciamento NUMA è vantaggioso sui sistemi multi-socket se i thread e la memoria rimangono locali. Applico i servizi ai nodi NUMA e monitoro le percentuali di miss locali. Le pagine enormi aumentano il throughput, ma controllo la frammentazione interna in modo da non avere regalare.
Cache del file system, mmap e percorsi di I/O
Gran parte della memoria „libera“ si trova nella cartella Cache di pagina. Decido consapevolmente se un motore utilizza la cache del sistema operativo (I/O bufferizzato) o la cache stessa (I/O diretto). Le cache doppie sprecano RAM; se la cache del sistema operativo è assente readahead-Lattanze. Per i carichi di lavoro di tipo stream, potrei aumentare il readahead per dispositivo; i database ad alta densità casuale funzionano meglio con l'I/O diretto.
# Esempio: aumentare il readahead a 256 settori
blockdev --setra 256 /dev/nvme0n1
I/O mappato in memoria (mmap) salva le copie, ma sposta la pressione sulla cache della pagina. In casi eccezionali, appendo le pagine critiche con mlock (o gli ulimiti di memlock) per evitare il jitter dovuto al recupero, sempre tenendo d'occhio le riserve del sistema.
Misure di emergenza rapide per la pressione della memoria
- Identificare i consumatori principali (ps/top/procdump) e riavviare o riprogrammare se necessario.
- Limitare temporaneamente la concorrenza (lavoratori/thread) per ridurre il tasso di errore e il writeback.
- Ridurre i limiti di sporcizia nel breve periodo, in modo da anticipare l'effetto del writeback e liberare le riserve.
- Per l'overcommit dei container, evacuare pod specifici; aumentare temporaneamente le risorse nelle macchine virtuali o rilassare il ballooning.
- Verifica della strategia OOM: attivare systemd-oomd/earlyoom e cgroup-in modo che i processi „giusti“ vengano eseguiti per primi.
Pianificazione della capacità e costi
La RAM costa, ma i guasti ripetuti costano in termini di entrate e di La reputazione. Per i server web e di database, di solito calcolo una riserva di 20-30% per coprire i rari picchi. Un modulo aggiuntivo da 64 GB per 180-280 euro spesso si ammortizza più rapidamente di una costante lotta agli incendi. Negli ambienti cloud, evito l'overbooking e prenoto i buffer in fasi che corrispondono ai modelli di carico. I calcoli sobri del TCO battono i grafici perché tengono conto dei danni da latenza e del tempo dell'operatore. prezzo in.
Riassumendo brevemente
A Server di paging della memoria Il sistema trae i maggiori benefici da una quantità sufficiente di RAM, da un'impostazione pulita di THP/pagine enormi e da un overcommit realistico. Mi affido a indicatori chiari come MByte disponibili, Byte accessibili e Pagine/secondo. Controllo due volte gli ambienti virtualizzati in modo che il ballooning e lo swap dell'host non rubino le prestazioni nascoste. Tengo i database lontani dallo swap con cache e limiti definiti. Se si attuano questi passaggi in modo coerente, si riducono le latenze, si previene il thrashing e si mantiene la Prestazioni stabile sui picchi di carico.


