Skip to content

Linux esegue lo "swapping opportunistico" o è un mito?

Ciao, abbiamo trovato la soluzione alla tua domanda, continua a leggere e la troverai poco più in basso.

Soluzione:

Linux non esegue lo "swapping 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. Documentation/admin-guide/sysctl/vm.rst. È la documentazione principale delle impostazioni regolabili della gestione della memoria virtuale di Linux.

Più precisamente:

10.6 Demone Pageout (kswapd)

Storicamente kswapd si svegliava ogni 10 secondi, ma ora viene svegliato dall'allocatore di pagine fisiche solo quando viene raggiunto il numero pages_low di pagine libere in una zona. [...] In condizioni di estrema pressione sulla memoria, i processi svolgeranno il lavoro di kswapd in modo sincrono. [...] kswapd continua a liberare pagine finché non viene raggiunta la soglia pages_high.

In base a quanto detto sopra, non ci si aspetta alcuno swapping quando il numero di pagine libere è superiore alla "filigrana alta".

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

Quando kswapd scrive una pagina di memoria in swap, libera immediatamente la pagina di memoria. kswapd non mantiene in memoria una copia della pagina swappata..

Linux 2.6 usa "rmap" per liberare la pagina. In Linux 2.4, la storia era più complessa. Quando una pagina era 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 aggressivo il kernel scambierà le pagine di memoria.
pagine di memoria. Valori più alti aumentano l'aggressività, mentre valori più bassi
diminuiscono la quantità di swap. Un valore di 0 indica al kernel di non avviare lo swap
di swap fino a quando la quantità di memoria libera e di pagine supportate da file è inferiore
meno del limite massimo in una zona.

Questa citazione descrive un caso speciale: se si configura il parametro swappiness per essere 0. In questo caso, inoltre, non ci si dovrebbe aspettare alcuno swapping fino a quando il numero di pagine di cache non sarà sceso alla soglia massima. In altre parole, il kernel cercherà di scartare quasi tutta la cache dei file prima di iniziare lo swapping. (Questo potrebbe causare forti rallentamenti. È necessario avere un po' di file cache! La cache dei file viene utilizzata per contenere il codice di tutti i programmi in esecuzione 🙂

Cosa sono le filigrane?

Le citazioni di cui sopra sollevano la domanda: Quanto sono grandi le riserve di memoria "filigrana" sul mio sistema? Risposta: su un sistema "piccolo", le filigrane di zona predefinite possono raggiungere il 3% della memoria. Ciò è dovuto al calcolo della filigrana "minima". Sui sistemi più grandi le filigrane saranno una percentuale minore, vicina 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 di watermark non sono significativi.

I watermark per ogni singola "zona" sono mostrati in /proc/zoneinfocome 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 "filigrane" attuali sono min, lowe high. Se un programma richiede una quantità di memoria tale da ridurre il valore di free sotto minil programma entra in "recupero diretto". Il programma deve attendere mentre il kernel libera la memoria.

Se possibile, vogliamo evitare il recupero diretto. Quindi se free scendesse al di sotto del valore low il kernel risveglia kswapd. kswapd libera la memoria con lo swapping e/o eliminando le cache, fino a quando free è superiore a high di nuovo.


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

Impegni per il codice di Linux

mm: scala i watermark di kswapd in proporzione alla memoria

[...]

fattore_scala_filigrana:

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

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

Un'alta frequenza di thread che entrano in direct reclaim (allocstall) o kswapd
di andare a dormire prematuramente (kswapd_low_wmark_hit_quickly) può indicare che il numero di pagine libere di kswapd
che il numero di pagine libere che kswapd mantiene per ragioni di latenza è
troppo piccolo per i burst di allocazione che si verificano nel sistema. Questa manopola
può essere usata per regolare di conseguenza l'aggressività di kswapd.

proc: meminfo: stima più prudente della memoria disponibile

Il MemAvailable in /proc/meminfo è quello di dare agli utenti un'indicazione di quanta
di quanta memoria è allocabile senza causare lo swapping, quindi esclude
le filigrane basse delle zone come non disponibili per lo spazio utente.

Tuttavia, per un'allocazione nello spazio utente, kswapd reclamerà effettivamente
fino a quando le pagine libere non raggiungono una combinazione tra l'high watermark e la protezione lowmem del
protezione lowmem dell'allocatore di pagine che mantiene una certa quantità di memoria DMA
e DMA32 dallo spazio utente.

Sottraete dal numero di pagine libere l'intera quantità che sappiamo non essere disponibile per lo spazio utente.
dal numero di pagine libere quando si calcola MemAvailable.

Codice Linux

A volte si sostiene che cambiare swappiness a 0 disabiliterà di fatto lo "swapping opportunistico". Questo fornisce un interessante spunto di indagine. Se esiste qualcosa chiamato "swapping opportunistico", e può essere regolato dalla swappiness, allora si potrebbe cercare di individuare tutte le catene di chiamate che leggono vm_swappiness. Si noti che possiamo ridurre lo spazio di ricerca assumendo che CONFIG_MEMCG non sia impostato (cioè i "gruppi di memoria" siano disabilitati). La catena di chiamate va:

  • vm_swappiness
  • mem_cgroup_swappiness
  • numero_di_scarichi
  • restringere_nodo_memcg
  • restringere_nodo

shrink_node_memcg è commentato "Si tratta di un liberatore di pagine di base per nodo. Utilizzato sia da kswapd che da direct reclaim". Vale a dire che questa funzione aumenta il numero di pagine di libero pagine libere. Non sta cercando di duplicare le pagine da scambiare in modo che possano essere liberate in un momento successivo. Ma anche se non teniamo conto di questo:

La catena di cui sopra viene chiamata da tre funzioni diverse, mostrate di seguito. Come ci si aspettava, possiamo dividere le chiamate in reclaim diretto e kswapd. Non avrebbe senso eseguire uno "swapping opportunistico" in direct reclaim.

  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 la richiesta è che kswapd venga 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 alcun risveglio di questo tipo.

No, non esiste lo swapping 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 recupera la memoria solo in risposta a qualche forma di pressione sulla memoria (con l'ovvia eccezione dell'ibernazione).

Tutte le idee sbagliate diffuse sull'argomento probabilmente derivano dal semplice fatto che Linux non può permettersi di aspettare l'ultimo byte di memoria libera prima di iniziare lo swapping. Ha bisogno di una sorta di cuscinetto per proteggersi da forme estreme di esaurimento della memoria, e ci sono alcune regolazioni che possono influenzare la dimensione di tale cuscinetto (ad esempio, la funzione " vm.min_free_kbytes" di Linux non è un problema.vm.min_free_kbytes). Ma non è la stessa cosa di "swappare perché non c'è niente di meglio da fare".

Sfortunatamente l'algoritmo di recupero delle pagine è diventato molto più complesso rispetto alla versione 2.6 (quando era descritto in dettaglio nel libro di Mel Gorman), ma l'idea di base è più o meno la stessa: il recupero delle pagine è innescato da allocazioni fallite, che poi o risvegliano kswapd o cercano di 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 pagine possono iniziare a fallire quando rimane abbastanza memoria libera è 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. Ciononostante, alcuni driver di periferica lo richiedono ancora, sia perché non possono eseguire I/O di memoria multipagina (DMA scatter-gather), sia perché potrebbe trattarsi di una codifica approssimativa da parte degli sviluppatori del driver. L'avvento delle Transparent Huge Pages (THP) ha fornito un'altra ragione per allocare la memoria in pezzi fisicamente contigui.

La compattazione a zone, introdotta nello stesso periodo, dovrebbe aiutare a risolvere il problema della frammentazione della memoria, ma non sempre produce l'effetto sperato.

Esistono vari vmscan che possono aiutare a capire cosa sta succedendo esattamente nel vostro caso specifico -- è sempre più facile trovare le cose necessarie nel codice del kernel Linux quando si hanno stack di chiamate specifici, piuttosto che scansionare tutto ciò che sembra lontanamente rilevante.

Se ti piace l'idea, hai il potere di lasciare un articolo su cosa aggiungeresti a questa cronaca.



Utilizzate il nostro motore di ricerca

Ricerca
Generic filters

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.