GNU/Linux >> Linux Esercitazione >  >> Linux

Linux esegue lo scambio opportunistico o è un mito?

Linux non esegue lo "scambio opportunistico" come definito in questa domanda.

I seguenti riferimenti primari non menzionano affatto il concetto:

  1. Capire il gestore della memoria virtuale di Linux. Un libro online di Mel Gorman. Scritto nel 2003, poco prima del rilascio di Linux 2.6.0.
  2. Documentazione/admin-guide/sysctl/vm.rst. Questa è la documentazione principale delle impostazioni sintonizzabili della gestione della memoria virtuale di Linux.

Più specificamente:

10.6 Demone Pageout (kswapd)

Storicamente kswapd prima si svegliava ogni 10 secondi, ma ora viene svegliato solo dall'allocatore di pagine fisiche quando viene raggiunto il numero di pagine libere in una zona. [...] Sotto estrema pressione della memoria, i processi faranno il lavoro di kswapd in modo sincrono. [...] kswapd continua a liberare le pagine finché non viene raggiunto il limite massimo di pagine.

Sulla base di quanto sopra, non ci aspetteremmo alcuno scambio quando il numero di pagine libere è superiore al "high watermark".

In secondo luogo, questo ci dice lo scopo di kswapd è creare più pagine libere.

Quando kswapd scrive una pagina di memoria da scambiare, libera immediatamente la pagina di memoria. kswapd non conserva in memoria una copia della pagina scambiata .

Linux 2.6 utilizza "rmap" per liberare la pagina. In Linux 2.4, la storia era più complessa. Quando una pagina veniva condivisa da più processi, kswapd non era in grado di liberarla immediatamente. Questa è storia antica. Tutti i post collegati riguardano Linux 2.6 o superiore.

swappiness

Questo controllo è usato per definire quanto aggressivamente il kernel scambierà le pagine di memoria. Valori più alti aumenteranno l'aggressività, valori più bassi diminuiranno la quantità di scambio. Un valore pari a 0 indica al kernel di non avviare lo scambio fino alla quantità di pagine libere e supportate da file è inferiore all'high water mark in una zona.

Questa citazione descrive un caso speciale:se configuri il swappiness il valore deve essere 0 . In questo caso, inoltre, non dovremmo aspettarci alcuno scambio fino a quando il numero di pagine della cache non sarà sceso al limite massimo. In altre parole, il kernel proverà a scartare quasi tutta la cache dei file prima di iniziare lo scambio. (Ciò potrebbe causare enormi rallentamenti. È necessario disporre di un po' di cache dei file! La cache dei file viene utilizzata per contenere il codice di tutti i programmi in esecuzione :-)

Cosa sono le filigrane?

Le citazioni sopra sollevano la domanda:quanto sono grandi le riserve di memoria "watermark" sul mio sistema? Risposta:su un sistema "piccolo", le filigrane di zona predefinite potrebbero raggiungere il 3% della memoria. Ciò è dovuto al calcolo della filigrana "min". Sui sistemi più grandi le filigrane saranno una proporzione minore, che si avvicina allo 0,3% della memoria.

Quindi, se la domanda riguarda un sistema con più del 10% di memoria libera, i dettagli esatti di questa logica della filigrana non sono significativi.

Le filigrane per ogni singola "zona" sono mostrate in /proc/zoneinfo , come documentato in proc(5). Un estratto dal mio zoneinfo:

Node 0, zone    DMA32
  pages free     304988
        min      7250
        low      9062
        high     10874
        spanned  1044480
        present  888973
        managed  872457
        protection: (0, 0, 4424, 4424, 4424)
...
Node 0, zone   Normal
  pages free     11977
        min      9611
        low      12013
        high     14415
        spanned  1173504
        present  1173504
        managed  1134236
        protection: (0, 0, 0, 0, 0)

Le attuali "filigrane" sono min , low e high . Se un programma richiede memoria sufficiente per ridurre free sotto min , il programma entra in "recupero diretto". Il programma viene fatto attendere mentre il kernel libera memoria.

Vogliamo evitare il recupero diretto, se possibile. Quindi se free scenderebbe sotto low watermark, il kernel riattiva kswapd . kswapd libera memoria scambiando e/o eliminando le cache, fino a free è superiore a high di nuovo.

Qualifica aggiuntiva:kswapd funzionerà anche per proteggere l'intera quantità lowmem_reserve, per l'utilizzo del kernel lowmem e DMA. Il lowmem_reserve predefinito è circa 1/256 dei primi 4GiB di RAM (zona DMA32), quindi di solito è di circa 16MiB.

Commit del codice Linux

mm:scala le filigrane kswapd in proporzione alla memoria

[...]

watermark_scale_factor:

Questo fattore controlla l'aggressività di kswapd. Definisce la quantità di memoria rimasta in un nodo/sistema prima che kswapd venga riattivato e quanta memoria deve essere libera prima che kswapd torni a dormire.

L'unità è in frazioni di 10.000. Il valore predefinito di 10 indica che le distanze tra le filigrane sono pari allo 0,1% della memoria disponibile nel nodo/sistema. Il valore massimo è 1000, o il 10% della memoria.

Un'alta percentuale di thread che entrano nel recupero diretto (allocstall) o che kswapd va in sospensione prematuramente (kswapd_low_wmark_hit_quickly) può indicare che il numero di pagine libere che kswapd mantiene per motivi di latenza è troppo piccolo per i picchi di allocazione che si verificano nel sistema. Questa manopola può quindi essere utilizzata per regolare l'aggressività di kswapd di conseguenza.

proc:meminfo:stima la memoria disponibile in modo più conservativo

Il MemAvailable elemento in /proc/meminfo è quello di dare agli utenti un suggerimento di quanta memoria è allocabile senza causare lo scambio, quindi esclude i limiti minimi delle zone come non disponibili per lo spazio utente.

Tuttavia, per un'allocazione dello spazio utente, kswapd verrà effettivamente recuperato fino a quando le pagine libere non raggiungono una combinazione di high watermark e protezione lowmem dell'allocatore di pagine che mantiene anche una certa quantità di memoria DMA e DMA32 dallo spazio utente.

Sottrai l'intero importo che sappiamo essere non disponibile per lo spazio utente dal numero di pagine libere durante il calcolo di MemAvailable.

Codice Linux

A volte si afferma che la modifica di swappiness a 0 disabiliterà efficacemente lo "scambio opportunistico". Ciò fornisce un'interessante via di indagine. Se c'è qualcosa chiamato "scambio opportunistico", e può essere regolato da swappiness, allora potremmo inseguirlo trovando tutte le catene di chiamate che leggono vm_swappiness . Nota che possiamo ridurre il nostro spazio di ricerca assumendo CONFIG_MEMCG non è impostato (cioè i "memory cgroups" sono disabilitati). La catena di chiamate va:

  • vm_swappiness
  • mem_cgroup_swappiness
  • get_scan_count
  • shrink_node_memcg
  • shrink_node

shrink_node_memcg è commentato "Questa è una pagina base per nodo più libera. Usata sia da kswapd che da direct reclaim". Cioè. questa funzione aumenta il numero di free pagine. Non sta tentando di duplicare le pagine da scambiare in modo che possano essere liberate in un secondo momento. Ma anche se lo escludiamo:

La catena sopra è chiamata da tre diverse funzioni, mostrate di seguito. Come previsto, possiamo dividere i siti di chiamata in bonifica diretta vs. kswapd. Non avrebbe senso eseguire "scambi opportunistici" nel recupero diretto.

  1. /*
     * This is the direct reclaim path, for page-allocating processes.  We only
     * try to reclaim pages from zones which will satisfy the caller's allocation
     * request.
     *
     * If a zone is deemed to be full of pinned pages then just give it a light
     * scan then give up on it.
     */
    static void shrink_zones
    
  2.  * kswapd shrinks a node of pages that are at or below the highest usable
     * zone that is currently unbalanced.
     *
     * Returns true if kswapd scanned at least the requested number of pages to
     * reclaim or if the lack of progress was due to pages under writeback.
     * This is used to determine if the scanning priority needs to be raised.
     */
    static bool kswapd_shrink_node
    
  3.  * For kswapd, balance_pgdat() will reclaim pages across a node from zones
     * that are eligible for use by the caller until at least one zone is
     * balanced.
     *
     * Returns the order kswapd finished reclaiming at.
     *
     * kswapd scans the zones in the highmem->normal->dma direction.  It skips
     * zones which have free_pages > high_wmark_pages(zone), but once a zone is
     * found to have free_pages <= high_wmark_pages(zone), any page in that zone
     * or lower is eligible for reclaim until at least one usable zone is
     * balanced.
     */
    static int balance_pgdat
    

Quindi, presumibilmente l'affermazione è che kswapd viene svegliato in qualche modo, anche quando tutte le allocazioni di memoria vengono soddisfatte immediatamente dalla memoria libera. Ho esaminato gli usi di wake_up_interruptible(&pgdat->kswapd_wait) , e non vedo risvegli come questo.


No, non esiste lo scambio opportunistico in Linux. Ho passato un po' di tempo a esaminare il problema e tutte le fonti (libri di testo, e-mail sulle liste di posta degli sviluppatori del kernel, codice sorgente di Linux e commenti sui commit e alcuni scambi su Twitter con Mel Gorman) mi dicono la stessa cosa:Linux rivendica solo memoria in risposta a qualche forma di pressione della memoria (con l'ovvia eccezione dell'ibernazione).

Tutti i malintesi popolari sull'argomento probabilmente derivano dal semplice fatto che Linux non può permettersi di aspettare fino all'ultimo byte di memoria libera prima di iniziare lo scambio. Ha bisogno di una sorta di cuscino per proteggerlo da forme estreme di esaurimento della memoria, e ci sono alcuni sintonizzabili che possono influenzare la dimensione di quel cuscino (ad es. vm.min_free_kbytes ). Ma non è la stessa cosa di "scambiare perché non c'è niente di meglio da fare".

Sfortunatamente l'algoritmo di page frame reclamation è diventato molto più complesso rispetto a 2.6 (quando era descritto in dettaglio nel libro di Mel Gorman), ma l'idea di base è più o meno la stessa:page reclamation è innescata da allocazioni fallite, che poi o sveglia kswapd oppure prova a liberare le pagine in modo sincrono (a seconda della pressione della memoria, dei flag di allocazione e di altri fattori).

La ragione più ovvia per cui le allocazioni di pagina potrebbero iniziare a fallire con sufficiente memoria libera rimanente è che potrebbero richiedere memoria contigua mentre in realtà la memoria potrebbe essere troppo frammentata per soddisfare la richiesta. Storicamente, gli sviluppatori del kernel Linux hanno fatto di tutto per evitare la necessità di allocazioni contigue. Tuttavia, alcuni driver di dispositivo lo richiedono ancora, o perché non possono eseguire I/O di memoria multipagina (DMA scatter-gather), o potrebbe essere solo una codifica sciatta da parte degli sviluppatori di driver. L'avvento di Transparent Huge Pages (THP) ha fornito un altro motivo per allocare la memoria in blocchi fisicamente contigui.

La compattazione delle zone, che è stata introdotta più o meno nello stesso periodo di tempo, dovrebbe aiutare con il problema della frammentazione della memoria, ma non sempre produce l'effetto previsto.

Ci sono vari vmscan punti di traccia che possono aiutare a capire cosa sta succedendo esattamente nel tuo caso specifico:è sempre più facile trovare le cose che ti servono nel codice del kernel Linux quando hai stack di chiamate specifici, piuttosto che scansionare tutto ciò che sembra remotamente rilevante.


Linux
  1. L'allocazione della memoria in Linux non è bloccante?

  2. Linux gratuito mostra un elevato utilizzo della memoria, ma top no

  3. Linux può ripulire la memoria?

  4. Memoria inattiva di Linux

  5. quali processi killer ha Linux?

Come cancellare la memoria di scambio in Linux

Come funziona la memoria di scambio in Linux?

Gestione della memoria Linux:scambio, cache e VM condivisa

Esempi di comandi gratuiti in Linux

Segmentazione della memoria di Linux

Come funziona l'allocazione dello stack in Linux?