Come può lo swapoff essere così lento?


79

In qualche modo mi è capitato di scambiare 14 GB di memoria. Dopo aver ucciso il colpevole, ho di nuovo tonnellate di memoria libera, quindi ho pensato di poter recuperare nuovamente i dati importanti . Quindi, con 5 GB su 32 GB utilizzati e 14 GB di spazio di swap utilizzati, ho eseguito swapoff -a.... e 4 ore dopo circa la metà del lavoro è stata completata.

Ciò significa meno di 1 MB / s, mentre posso facilmente copiare 200 MB / s. Il mio swap è crittografato, ma lo sono anche tutte le partizioni normali e con aes-ni non comporta alcun notevole carico della CPU (e riempire lo spazio di swap ha richiesto solo pochi minuti). Vedo che non esiste un motivo speciale per l'ottimizzazione swapoff, tuttavia mi chiedo come potrebbe essere così lento?


Aggiungo solo altri dati: la mia memoria principale è di 32 GB e ho 32 GB di spazio di swap su ciascuno dei 4 dischi rigidi (sicuramente un problema eccessivo, ma a chi importa?). L'intero spazio di scambio può essere (decrittografato e) letto in meno di 5 minuti:

time -p sudo sh -c 'for i in /dev/mapper/cryptswap?; do md5sum $i & done; wait'
014a2b7ef300e11094134785e1d882af  /dev/mapper/cryptswap1
a6d8ef09203c1d8d459109ff93b6627c  /dev/mapper/cryptswap4
05aff81f8d276ddf07cf26619726a405  /dev/mapper/cryptswap3
e7f606449327b9a016e88d46049c0c9a  /dev/mapper/cryptswap2
real 264.27

La lettura di una parte di una partizione non può essere più lenta della lettura di tutto. Tuttavia, leggere circa 1/10 di esso richiede circa 100 volte di più.

Ho osservato che in swapoffentrambi i casi la CPU era principalmente inattiva (forse il 10% di un core) e così anche i dischi ("misurati" dai LED). Ho anche visto che gli spazi di swap erano disattivati ​​uno dopo l'altro.


1
Mi chiedo, lo stesso fenomeno si verifica quando il sistema carica di nuovo le pagine scambiate nella RAM? Ad esempio, se un sistema è stato sospeso su disco e quindi avviato, tutto è stato scambiato e viene ricaricato nella RAM. Sembra essere molto lento anche per me.
Petr Pudlák,

Tutti i dispositivi di scambio sono attivati ​​con la stessa priorità?
Nils,

@Petr Pudlák: La sospensione su disco è un po 'diversa, scrive semplicemente il contenuto della RAM in uno spazio libero nell'area di scambio, e questo (e non sospenderlo) è probabilmente molto più veloce. Non posso provare in quanto non funziona con lo scambio crittografato.
maaartinus,

@Nils: Sì, la priorità è la stessa, così come il disco e il loro partizionamento.
maaartinus,

Questo lo rende più strano. In questo caso lo swap è a strisce su tutti i dischi - questo dovrebbe essere molto veloce. Ha iostat -d 5mostrato anche un IO basso sui dischi durante swapoff?
Nils,

Risposte:


53

Innanzitutto, diamo un'occhiata a cosa puoi aspettarti dal tuo disco rigido. Il disco rigido può eseguire 200 MB / s in sequenza . Quando consideri i tempi di ricerca, può essere molto più lento. Per scegliere un esempio arbitrario, dai un'occhiata alle specifiche di uno dei moderni dischi da 3 TB di Seagate, ST3000DM001 :

  • Velocità dati sostenuta massima: 210 MB / s

  • Cerca lettura media: <8,5 ms

  • Byte per settore: 4.096

Se non hai mai bisogno di cercare e se lo swap è vicino al bordo del disco, puoi aspettarti di vedere fino alla velocità massima = 210 MB / s

Ma se i tuoi dati di swap sono completamente frammentati, nel peggiore dei casi, dovrai cercare in giro per ogni settore che leggi. Ciò significa che puoi leggere solo 4 KB ogni 8,5 ms o 4 KB / 0,0085 = 470 KB / s

Quindi, subito, non è inconcepibile che tu stia effettivamente correndo contro la velocità del disco rigido.


Detto questo, sembra sciocco swapoffcorrere così lentamente e dover leggere le pagine fuori servizio, specialmente se sono state scritte rapidamente (il che implica in ordine). Ma potrebbe essere solo così che funziona il kernel. La segnalazione bug # 486666 di Ubuntu tratta lo stesso problema:

The swap is being removed at speed of 0.5 MB/s, while the
hard drive speed is 60 MB/s;
No other programs are using harddrive a lot, system is not under
high load etc.

Ubuntu 9.10 on quad core.

Swap partition is encrypted.
Top (atop) shows near 100% hard drive usage
  DSK | sdc | busy 88% | read 56 | write 0 | avio 9 ms |
but the device transfer is low (kdesysguard)
  0.4 MiB/s on /dev/sdc reads, and 0 on writes

Una delle risposte è stata:

It takes a long time to sort out because it has to rearrange and flush the
memory, as well as go through multiple decrypt cycles, etc. This is quite
normal

La segnalazione di bug è stata chiusa irrisolta.

Il libro di Mel Gorman " Capire il gestore della memoria virtuale Linux " è un po 'obsoleto, ma concorda sul fatto che si tratta di un'operazione lenta:

La funzione responsabile della disattivazione di un'area è, abbastanza prevedibilmente, chiamata sys_swapoff(). Questa funzione riguarda principalmente l'aggiornamento di swap_info_struct. Il compito principale del paging in ogni pagina di paging è la cui responsabilità try_to_unuse()è estremamente costosa.

C'è un po 'più di discussione dal 2007 sulla mailing list del kernel Linux con l'oggetto " speeding up swapoff " - anche se le velocità di cui stanno discutendo sono un po' più alte di quello che stai vedendo.


È una domanda interessante che probabilmente viene generalmente ignorata, poiché swapoffviene utilizzata raramente. Penso che se si voleva davvero rintracciarlo, il primo passo sarebbe cercare di guardare i vostri modelli di utilizzo del disco con più attenzione (magari con atop, iostat, o anche strumenti più potenti come perfo systemtap). Le cose da cercare potrebbero essere la ricerca eccessiva, le piccole operazioni di I / O, la costante riscrittura e lo spostamento dei dati, ecc.


5
Spiegazione eccellente. Va notato che è possibile aggirare la maggior parte della frammentazione e liberare rapidamente la maggior parte degli swap scaricando core le grandi sezioni della memoria scambiata: unix.stackexchange.com/questions/254202/…
Brandon DuPree

1
Non è solo tempo di frammentazione / ricerca. Il mio scambio è su SSD e le letture casuali sono molto veloci, tuttavia il comando swapoff è molto più lento di quanto dovrebbe e il mio carico SSD si attesta all'1% circa. Sospetto che ci siano list-walking coinvolti da qualche parte nel kernel o in swapoff (che usa una CPU del 90-100%). Naturalmente se tutto il lavoro viene eseguito in sequenza e anche la ricerca del disco è lenta, può sommarsi in modo significativo.
Thomas Guyot-Sionnest,

34

Ho riscontrato lo stesso problema con il mio laptop che ha un SSD, quindi i tempi di ricerca non dovrebbero essere un problema.

Ho trovato una spiegazione alternativa . Ecco un estratto

Nel modo in cui funziona ora, swapoff osserva ogni pagina di memoria scambiata nella partizione di swap e cerca di trovare tutti i programmi che la utilizzano. Se non riesce a trovarli immediatamente, esaminerà le tabelle delle pagine di ogni programma in esecuzione per trovarli. Nel peggiore dei casi, controllerà tutte le tabelle delle pagine per ogni pagina scambiata nella partizione. Esatto: le stesse tabelle di pagine vengono verificate più volte.

Quindi è un problema del kernel piuttosto che altro.


1
No, non è un problema del kernel IMHO. È come swapoffviene implementato. Quando il processo di scambio termina, non ci vuole molto tempo.
Marki555,

15
È un problema con l'implementazione di swapoff che si trova nel kernel - quindi un problema con il kernel! Puoi vedere se strace swapofftutto ciò che fa è chiamare la swapoffchiamata di sistema.
Nick Craig-Wood,

1
Ho un server con 48 GB di RAM (32 core), con 6 GB di scambio gratuito di bug è stato usato 0,7 GB. swappiness = 10, ha provato a renderlo 0 e ha anche provato lo swapoff per vedere cosa succede. swapoff impiega anni, probabilmente 30 minuti, rilasciando lo swap estremamente lento. Ho SSD quasi senza carico e la CPU è simile, mi aspetto il processo di scambio che richiede una CPU al 100%.
sorin,

1
È un problema di come viene implementato swapoff (nel kernel). Ci sono state discussioni su un approccio molto migliore qualche anno fa in kernel-dev, ma dicono che è un caso fondamentale e non vogliono lo sforzo di cambiarlo.
Marki555,

7
Su server con 1 TB di RAM (sì, TB) e 2 GB di swap (requisito SAP sciocco) lo swapoff ha richiesto 12 ore per liberare il 5% di quei 2 GB (con 1 core CPU al 100%).
Marki555,

22

Sì, il swapoffmeccanismo è terribilmente inefficiente. La soluzione è semplice: iterare sui processi, invece iterare sulle pagine scambiate. Usa questo script Python (non sono affiliato):

git clone https://github.com/wiedemannc/deswappify-auto

Si noti che la modalità operativa daemon è solo per desktop / laptop che sono spesso in letargo. Non lo eseguirò come un demone su un sistema server - eseguirlo solo in primo piano, attendere fino a quando segnala che si è preso cura di alcuni processi, quindi fermarlo e provare:

swapoff /dev/x

Dal momento che la maggior parte delle pagine è ora presente sia in swap che in memoria, swapoffha poco da fare e ora dovrebbe essere incredibilmente veloce (ho visto centinaia di MB / s).

Sezione di storia a venire

Il suddetto script di Python si basa sul resto di questa risposta, che a sua volta è stato il mio miglioramento di questa risposta più antica creata da Jlong . Poiché lo script è molto più sicuro, ti consiglio di provare solo il resto della mia risposta come ultima linea di difesa :

perl -we 'for(`ps -e -o pid,args`) { if(m/^ *(\d+) *(.{0,40})/) { $pid=$1; $desc=$2; if(open F, "/proc/$pid/smaps") { while(<F>) { if(m/^([0-9a-f]+)-([0-9a-f]+) /si){ $start_adr=$1; $end_adr=$2; }  elsif(m/^Swap:\s*(\d\d+) *kB/s){ print "SSIZE=$1_kB\t gdb --batch --pid $pid -ex \"dump memory /dev/null 0x$start_adr 0x$end_adr\"\t2>&1 >/dev/null |grep -v debug\t### $desc \n" }}}}}' | sort -Vr | head

Questo dura forse 2 secondi e in realtà non farà nulla, basta elencare i primi 10 segmenti di memoria (in realtà stampa più linee singole; sì , adoro le linee singole; basta esaminare i comandi, accettare il rischio, copiare e incollare in la tua shell; questi in realtà leggeranno da swap).

...Paste the generated one-liners...
swapoff /your/swap    # much faster now

Il one-liner principale è sicuro (per me), tranne per il fatto che legge molto / proc.

I comandi secondari preparati per l'esame manuale non sono sicuri . Ogni comando bloccherà un processo per la durata della lettura di un segmento di memoria da swap. Quindi non è sicuro con processi che non tollerano alcuna pausa. Le velocità di trasferimento che ho visto erano dell'ordine di 1 gigabyte al minuto. (Il summenzionato script Python ha rimosso tale carenza).

Un altro pericolo è mettere troppa pressione di memoria sul sistema, quindi verificare con il solito free -m

Che cosa fa?

for(`ps -e -o pid,args`) {

  if(m/^ *(\d+) *(.{0,40})/) { 
    $pid=$1; 
    $desc=$2; 

    if(open F, "/proc/$pid/smaps") { 

      while(<F>) { 

        if(m/^([0-9a-f]+)-([0-9a-f]+) /si){ 
          $start_adr=$1; 
          $end_adr=$2; 
        } elsif( m/^Swap:\s*(\d\d+) *kB/s ){
          print "SSIZE=$1_kB\t gdb --batch --pid $pid -ex \"dump memory /dev/null 0x$start_adr 0x$end_adr\"\t2>&1 >/dev/null |grep -v debug\t### $desc \n" 
        }
      }
    }
  }
}

L'output di questo script perl è una serie di gdbcomandi dump memory (range)che richiamano in memoria le pagine scambiate.

L'output inizia con la dimensione, quindi è abbastanza facile passarlo attraverso | sort -Vr | headper ottenere i primi 10 segmenti più grandi per dimensione (SSIZE). Le -Vtribune per l'ordinamento version-number-adatto, ma funziona per il mio scopo. Non riuscivo a capire come far funzionare l'ordinamento numerico.


In questo caso useresti un ordinamento numerico consort -t = -k 2n
Stéphane Chazelas,

9
Non sembra esserci alcuna necessità di usare gdb per sbirciare la memoria di processo (almeno sui kernel recenti). Si può semplicemente aprire /proc/$pid/mem, cercare e leggere direttamente. Ecco PoC in gran parte basato sul tuo frammento: gist.github.com/WGH-/91260f6d65db88be2c847053c49be5ae In questo modo il processo non viene interrotto, AFAIK non dovrebbe esserci alcun pericolo causato da questo.
WGH,

10

Durante lo scambio, se viene rilevato uno slot di scambio in uso, il kernel scambia prima la pagina. La funzione unuse_process () quindi cerca di trovare tutte le voci della tabella delle pagine che corrispondono alla pagina appena scambiata e rende necessario l'aggiornamento alle tabelle delle pagine. La ricerca è esaustiva e richiede molto tempo: visita ogni descrittore di memoria (dell'intero sistema) ed esamina le voci della tabella delle pagine una per una.

Fare riferimento a pagina 724 di "Comprensione della terza versione del kernel Linux".

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.