Come domare la reattività, la memoria e il paging di Linux


27

Prima domanda su overflow =) ... +100 taglia. Non riuscivo a pensare a qualcosa a cui tenevo davvero fino ad ora:

Sono davvero stufo dello stato di reattività del desktop Linux, ad esempio http://brainstorm.ubuntu.com/item/85/ - in situazioni con RAM libera libera o situazioni con un throughput del disco elevato, il sistema rallenta un gattonare ; questo è assolutamente terribile per le applicazioni che richiedono prestazioni decenti. Inoltre, l'interfaccia utente non risponde completamente. Confronta questo ad esempio con OS X, dove se un'applicazione sta eseguendo il hogging delle risorse, puoi sempre fare clic sull'opzione per forzare l'uscita, mentre in Linux non posso nemmeno alt-tab o cambiare desktop, o anche ctrl-alt-f1 per ottenere un terminale - bene posso, bastano circa 1-2 minuti per operazione.

Uso gkrellm in modo da poter vedere la situazione mentre si svolge. In genere l'utilizzo della memoria diventa piuttosto elevato o il throughput del disco salta in modo drammatico.

Non è un hardware difettoso, con un quad-core a 2,6 GHz e 4 GB di RAM DDR2 a 800 MHz (avrebbe avuto 6 GB, ma a causa di un'incompatibilità hardware non poteva combinarsi con il vecchio set). Questo problema potrebbe scomparire quando inevitabilmente avessi più RAM, ma non credo che questo sia il cuore del problema. Ho anche due partizioni di swap su dischi diversi.

Sento che il problema è triplice:

  • programmi in fuga che ingombrano enormi quantità di memoria - la legge deve essere stabilita per questi programmi, con limiti ai loro
    • (ad esempio schede su Chrome, ognuna delle quali è 20-50 MB, alcune delle quali possono utilizzare centinaia di MB)
    • (ad esempio altri programmi come update-db e gli indicizzatori che ho dovuto disabilitare e rimuovere da cron perché rallentavano il sistema a una scansione ogni volta che venivano eseguiti, ecc.)
  • qualcosa di terribile che sta succedendo nel conflitto del kernel o del bus di qualche tipo, in modo tale che situazioni di throughput elevato del disco rallentino l'intero sistema a una scansione (forse eseguendo il paging di programmi importanti)
  • il kernel non sta dando la priorità all'interfaccia utente o ai programmi importanti in termini di risorse, come memoria, paging e persino l'utilizzo del processore

I voti vanno a:

Sto quindi cercando una soluzione in cui tutti questi programmi scompaiano. In particolare, sto cercando una soluzione tale che i processi rallentino in modo proporzionale, mentre il sistema e altri programmi rimangono completamente inalterati e reattivi abbastanza a lungo da uccidere manualmente qualcosa. Anche il processo di gestione delle finestre (e qualsiasi altra cosa che possa influire sulla reattività dell'interfaccia utente) dovrebbe essere reattivo in tutte le circostanze.

In particolare sono incuriosito da /etc/security/limits.conf( man limits.conf), ma sono preoccupato che ciò dia solo il controllo per utente, e gli esempi commentati nel file sembrano piuttosto opachi in termini di descrizione o da dove cominciare. Spero che limits.conffunzioni, ma non sarei sorpreso se non funzionasse nemmeno, o se non fosse una soluzione adeguata al mio problema, o granulare come sto cercando di ottenere. Un nome per processo limits.confsarebbe l'ideale, supponendo nuovamente che limits.conf funzioni. Sarei felice di provare un limits.conf che le persone forniscono, per verificare se funziona, anche se a questo punto sono aperto a tutte le soluzioni.

Potrebbe anche essere utile avere approfondimenti su come OS X riesce a mantenere una buona capacità di risposta dell'interfaccia utente.

Ho già ottimizzato le /tmpcartelle my e cache per essere attive tmpfs, e in generale l'utilizzo del disco è quasi zero.

Argomenti vagamente correlati:

  • sovraccarico di memoria

Risposte che non credo funzioneranno:

  • swapoff (questo consente ancora ai programmi di hog della memoria di cavarsela con l'omicidio e il sistema si blocca in modo permanente se la memoria è davvero pessima - voti a chiunque possa suggerire una modifica che ha invocato l'OOM-killer prima di scambiare e indirizzare programmi specifici)
  • echo ?? > /sys/.../swappiness (nessun effetto riconoscibile)
  • nice (non ha mai funzionato)
  • ionice (mai notato una differenza)
  • selinux (l'incompatibilità del programma sembra essere un incubo)
  • Linux in tempo reale, ovvero può interrompere il kernel (non voglio occuparsi della compilazione e dell'aggiornamento del kernel personalizzato; potrebbe andare bene se è migrato in repository)
  • *

hmm, non riesco a piazzare una taglia; Suppongo che il link non venga visualizzato per 48 ore? ... Bene, pubblicherò la taglia con tutta la reputazione che ho acquisito allora
user76871

1
+1, questo è il problema più grande che ho con il desktop Linux su una base quotidiana. Ho dei congelamenti occasionali, forse una volta ogni due settimane, ma quelli non sono abbastanza spesso da diventare particolarmente fastidiosi. Tuttavia, sembra solo essere un problema con le applicazioni che hanno, come hai detto, un forte utilizzo dell'IO : le applicazioni che hanno un utilizzo intenso della CPU non hanno alcun effetto sulle prestazioni generali del sistema. Non sapevo di ionice, sembra che sarebbe la soluzione corretta a questo problema se funzionasse correttamente.
crazy2be

1
3 anni dopo e questo è ancora un problema su Linux. @ crazy2be o user76871, suppongo che tu non abbia trovato una soluzione nel frattempo?
Glutanimate,

@Glutanimate: sì, 32 GB di RAM fisica e non meno (beh, forse 16 GB ... ma questo lo sta spingendo), ma potrebbe anche essere una grande quantità di RAM video. Ciò non risolve la mancata risposta a causa di CPU elevata o interruzioni o quant'altro, ma impedisce la non risposta in situazioni di memoria insufficiente.
user76871

Risposte:


6

Sembra che il tuo sistema subisca pesanti scambi. L'uso vmstat 1potrebbe rivelare alcuni dettagli: basta lasciarlo funzionare in una finestra del terminale e passare ad esso quando inizia il rallentamento.

Invece di mettere / tmp e "cache" in tmpfs, userei un normale filesystem su disco montato con l' noatimeopzione. Spesso i dati utilizzati rimangono comunque nella cache e i dati più vecchi possono essere scritti su disco per liberare un po 'di RAM per le applicazioni. Se / tmp e / o cache diventano più grandi, questo potrebbe aiutare molto.


1
+1 per la menzione noatime.
LawrenceC,

Grazie per averlo menzionato noatime, sfortunatamente usavo quell'opzione mount e non credo che abbia aiutato molto a garantire la reattività (anche se aiuta un sacco a garantire che il disco non sia sovraccarico di lavoro); solo per essere sicuro di aver riattivato noatime sulla mia configurazione attuale. Avere un non-tmpfs con noatime sembra un po 'strano, dato che immagino ancora che debbano accadere scritture di massa.
user76871,

+1, provato vmstat 1- estremamente utile per confermare la diagnosi che lo scambio è, in effetti, una grande parte del problema principale del problema
user76871

2
Ahia. Non ho mai visto un sistema Linux che necessitasse di uno scambio così pesante. Hai controllato con df -mquanta memoria viene utilizzata nei filesystem tmpfs? Qualcosa sta consumando la tua RAM relativamente velocemente.
Turbo J,

grazie per il suggerimento e per avermi insegnato -msull'opzione. Sfortunatamente df -h -msembra indicare che sono presenti solo 100 MB della mia memoria tmpfs, quindi dubito che sia correlato all'utilizzo della memoria per tmpfs e cache. Anche questo non sembra così raro; Ho avuto successo su più distribuzioni quando la loro RAM è stata spinta quasi al limite.
user76871,

5

Non sono uno sviluppatore del kernel, ma ho passato anni a filosofare su questo problema perché mi sono imbattuto in questo moltissime volte. In realtà ho inventato una metafora per l'intera situazione, quindi lascia che te lo dica. Presumo nella mia storia che cose come "swap" non esistano. Al giorno d'oggi Swap non ha molto senso con 32 GB di RAM.

Immagina un tuo quartiere in cui l'acqua è collegata a ciascun edificio attraverso tubi e le città devono gestire la capacità. Supponiamo che tu abbia solo una produzione di 100 unità di acqua al secondo (e tutta la capacità inutilizzata va sprecata perché non hai serbatoi). Ogni casa (home = una piccola app, un terminale, il widget dell'orologio, ecc.) Richiede 1 unità di acqua al secondo. Tutto questo è bello e buono perché la tua popolazione è come 90, quindi tutti hanno abbastanza acqua.

Ora il sindaco (= tu) decide di voler aprire un ristorante di grandi dimensioni (= browser). Questo ristorante ospiterà più cuochi (= schede del browser). Ogni cuoco ha bisogno di 1 unità di acqua al secondo. Si inizia con 10 cuochi, quindi il consumo totale di acqua per l'intero quartiere è di 100 unità di acqua che è ancora tutto buono.

Ora iniziano le cose divertenti: assumi un altro cuoco nel tuo ristorante che rende il fabbisogno totale di acqua 101 che ovviamente non hai. Devi fare qualcosa.

La gestione dell'acqua (= kernel) ha 3 opzioni.

1. La prima opzione è semplicemente disconnettere il servizio per le case che non hanno usato l'acqua di recente. Questo va bene, ma se la casa disconnessa vuole riutilizzare l'acqua, dovrà ripetere il lungo processo di registrazione. La direzione può disconnettere più case per liberare più risorse idriche. In realtà, disconnetteranno tutte le case che non hanno usato acqua di recente mantenendo così una certa quantità di acqua gratuita sempre disponibile.

Sebbene la tua città continui a funzionare, il rovescio della medaglia è che i progressi si fermano. La maggior parte del tempo viene impiegato in attesa della gestione delle risorse idriche per ripristinare il servizio.

Questo è ciò che fa il kernel con le pagine supportate da file. Se esegui un eseguibile di grandi dimensioni (come Chrome), il suo file viene copiato nella memoria. Quando la memoria è insufficiente o se ci sono parti a cui non è stato effettuato l'accesso di recente, il kernel può rilasciarle perché può comunque ricaricarle dal disco. Se ciò viene fatto in modo eccessivo, questo blocca il desktop perché tutti aspetteranno l'IO del disco. Nota che il kernel rilascerà anche molte delle pagine usate meno di recente quando inizi a fare molto IO. Ecco perché ci vogliono anni per passare a un'app in background dopo aver copiato diversi file di grandi dimensioni come immagini DVD.

Questo è il comportamento più fastidioso per me perché odio il singhiozzo e non hai alcun controllo su di esso. Sarebbe bello poterlo spegnere. Sto pensando a qualcosa del genere

sed -i 's/may_unmap = 1/may_unmap = (vm_swappiness >= 0)/' mm/vmscan.c

e quindi è possibile impostare vm_swappiness su -1 per disabilitarlo. Questo ha funzionato abbastanza bene nei miei piccoli test ma purtroppo non sono uno sviluppatore del kernel, quindi non l'ho inviato a nessuno (e ovviamente la piccola modifica sopra non è completa).

2.La direzione potrebbe negare la richiesta di acqua del nuovo cuoco. Questa inizialmente sembra una buona idea. Tuttavia ci sono due aspetti negativi. Innanzitutto, ci sono aziende che richiedono molti abbonamenti idrici anche se non li usano. Una possibile ragione per farlo è evitare tutto il sovraccarico di parlare con la gestione dell'acqua ogni volta che hanno bisogno di un po 'd'acqua in più. Il loro consumo di acqua aumenta e diminuisce a seconda dell'ora del giorno. Ad esempio nel caso del ristorante, la società ha bisogno di molta più acqua a mezzogiorno rispetto a mezzanotte. Quindi richiedono tutta l'acqua possibile che potrebbero usare, ma ciò spreca allocazioni di acqua durante la mezzanotte. Il problema è che non tutte le aziende possono prevedere correttamente il loro picco di utilizzo, quindi richiedono molto di più nella speranza che non debbano mai preoccuparsi di richiedere di più.

Questo è ciò che fa la macchina virtuale Java: alloca un sacco di memoria all'avvio e quindi funziona da quello. Per impostazione predefinita, il kernel alloca la memoria solo quando l'app Java inizia effettivamente a usarla. Tuttavia, se si disabilita l'overcommit, il kernel prenderà sul serio la prenotazione. Permetterà che l'allocazione abbia successo solo se ha effettivamente le risorse per esso.

Tuttavia, c'è un altro problema più serio con questo approccio. Supponiamo che una società inizi a richiedere una singola unità di acqua ogni giorno (anziché con incrementi di 10). Alla fine raggiungerai uno stato in cui hai 0 unità libere. Ora questa azienda non sarà in grado di allocare di più. Va bene, chi se ne frega comunque delle grandi aziende. Ma il problema è che le piccole case non saranno in grado di richiedere più acqua! Non sarai in grado di costruire piccoli bagni pubblici per far fronte all'improvviso afflusso di turisti. Non sarai in grado di fornire acqua di emergenza per l'incendio nella foresta vicina.

In termini di computer: in situazioni di memoria molto bassa senza overcommit non sarai in grado di aprire un nuovo xterm, non sarai in grado di ssh nel tuo computer, non sarai in grado di aprire una nuova scheda per cercare possibili correzioni. In altre parole, disabilitare l'overcommit rende il desktop inutile anche quando la memoria è insufficiente.

3. Ora ecco un modo interessante di gestire il problema quando un'azienda inizia a usare troppa acqua. La gestione dell'acqua fa esplodere! Letteralmente: va nel sito del ristorante, vi lancia dinamiti e aspetta che esploda. Ciò ridurrà istantaneamente di molto il fabbisogno idrico della città in modo che nuove persone possano trasferirsi, creare bagni pubblici, ecc. Tu, come sindaco, puoi ricostruire il ristorante nella speranza che questa volta richiederà meno acqua. Ad esempio, dirai alle persone di non andare nei ristoranti se ci sono già troppe persone all'interno (ad esempio, aprirai meno schede del browser).

Questo è in realtà ciò che fa il kernel quando esaurisce tutte le opzioni e ha bisogno di memoria: chiama il killer OOM. Prende un'applicazione di grandi dimensioni (basata su molte euristiche) e la uccide, liberando un sacco di memoria ma mantenendo un desktop reattivo. In realtà il kernel Android lo fa in modo ancora più aggressivo: uccide l'app utilizzata meno di recente quando la memoria è scarsa (rispetto al kernel stock che lo fa solo come ultima risorsa). Questo si chiama Viking Killer in Android.

Penso che questa sia una delle soluzioni più semplici al problema: non è che tu abbia più opzioni di così, quindi perché non superarlo prima o poi, giusto? Il problema è che il kernel a volte fa parecchio lavoro per evitare di invocare il killer OOM. Ecco perché vedi che il tuo desktop è molto lento e il kernel non sta facendo nulla al riguardo. Ma per fortuna c'è un'opzione per invocare te stesso l'assassino OOM! Innanzitutto, assicurati che il tasto sysrq magico sia abilitato (ad es. echo 1 | sudo tee /proc/sys/kernel/sysrq) Ogni volta che ritieni che il kernel stia esaurendo la memoria, premi Alt + SysRQ, Alt + f.

OK, allora è tutto carino, ma vuoi provarlo? La situazione di memoria insufficiente è molto semplice da riprodurre. Ho un'app molto semplice per questo. Dovrai eseguirlo due volte. Il primo avvio determinerà la quantità di RAM libera disponibile, il secondo eseguirà la situazione di memoria insufficiente. Si noti che questo metodo presuppone che lo swap sia disabilitato (ad es. Fare a sudo swapoff -a). Segue codice e utilizzo:

// gcc -std=c99 -Wall -Wextra -Werror -g -o eatmem eatmem.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char** argv)
{
    int limit = 123456789;
    if (argc >= 2) {
        limit = atoi(argv[1]);
    }
    setbuf(stdout, NULL);
    for (int i = 1; i <= limit; i++) {
        memset(malloc(1 << 20), 1, 1 << 20);
        printf("\rAllocated %5d MiB.", i);
    }
    sleep(10000);
    return 0;
}

Ed ecco come lo usi:

$ gcc -std=c99 -Wall -Wextra -Werror -g -o eatmem eatmem.c
$ ./eatmem
Allocated 31118 MiB.Killed
$ ./eatmem 31110
Allocated 31110 MiB.Killed

La prima invocazione ha rilevato che abbiamo 31.118 MiB di RAM libera. Quindi ho detto all'applicazione di allocare 31.110 MiB RAM in modo che il kernel non la uccidesse ma consumasse quasi tutta la mia memoria. Il mio sistema si è bloccato: anche il puntatore del mouse non si è mosso. Ho premuto Alt + SysRQ, Alt + f e ha interrotto il mio processo EatMem e il sistema è stato ripristinato.

Anche se abbiamo coperto le nostre opzioni su cosa fare in una situazione di memoria insufficiente, l'approccio migliore (proprio come qualsiasi altra situazione pericolosa) è quello di evitarlo in primo luogo. Ci sono molti modi per farlo. Un modo comune che ho visto è quello di mettere le applicazioni che si comportano male (come i browser) in contenitori diversi rispetto al resto del sistema. In tal caso il browser non sarà in grado di influire sul desktop. Ma la prevenzione stessa è al di fuori del campo di applicazione della domanda, quindi non ne scriverò.

TL; DR: sebbene al momento non sia possibile evitare completamente il paging, è possibile mitigare l'arresto completo del sistema disabilitando l'overcommit. Ma il tuo sistema sarà ancora inutilizzabile in situazioni di memoria insufficiente, ma in modo diverso. Indipendentemente da quanto sopra, in una situazione di memoria insufficiente premere Alt + SysRQ, Alt + f per terminare un grosso processo a scelta del kernel. Il sistema dovrebbe ripristinarne la reattività dopo alcuni secondi. Questo presuppone che tu abbia la chiave sysrq magica abilitata (non è di default).


Ti ho dato tutta la mia reputazione di generosità su questa risorsa, quindi non potevo nemmeno lasciare un commento :) Infine, ne ho guadagnato alcuni per ringraziarti per questa grande risposta! Ho avuto a che fare con questo problema tutto il tempo che avevo il mio laptop con 8 GB (pazzo, ma il mio sistema stava esaurendo la memoria regolarmente in quei giorni). Di recente, ho trovato questo progetto: github.com/rfjakob/earlyoom , che potrebbe aiutare a prevenire il blocco del sistema uccidendo alcuni processi prima che sia troppo tardi.
Vlad Frolov,

4

Mettere tutti i tuoi file temporanei e cache su a tmpfssta riducendo la quantità di RAM libera che hai, quindi potresti causare lo scambio del sistema prima di quanto sarebbe necessario senza questo.

Sembra che tu abbia alcune applicazioni che fanno affidamento su una sorta di funzione o driver del kernel che viene sovraccaricato. Non approfondisci troppo i tipi di applicazioni diversi da quelli che stai utilizzando browser e indicizzatori e che hai disabilitato gli indicizzatori.

Potresti provare a passare a un ambiente desktop o gestore di finestre che consuma meno risorse, come LXDE o IceWM. Al lavoro uso un sistema Linux con LXDE installato e ROX-Filer per un ambiente desktop molto minimale. Lo scopo di questo sistema Linux è eseguire VMWare Player in modo da poter eseguire contemporaneamente Windows XP e Windows 7. Sono specifiche hardware simili a quelle che dici e non ho troppi problemi di reattività sotto questo carico pesante che sto attraversando. Non ho alcun problemi di risposte con Linux stesso (di solito le macchine virtuali che a volte mi fanno aspettare un secondo, e la condivisione di 1 disco tra 2 VM + 1 OS questo è previsto) e sono sempre stati in grado di sospendere o spegnere il VM ogni volta Voglio.

Quindi per me indica un problema con applicazioni specifiche in esecuzione.

DMA è abilitato per le unità disco? (uso hdparm) Se si utilizza la crittografia dell'intero disco, ciò richiede che tutto il traffico su disco passi attraverso la CPU, il che annulla gran parte del vantaggio di DMA. L'effetto sarebbe che l'elevato traffico su disco causerebbe un picco della CPU che rallenterebbe quindi l'intero sistema. (MODIFICA: per chiarire, la disabilitazione di DMA o l'utilizzo dm-cryptcausa CPU elevata durante il traffico su disco elevato)


2
Il punto della domanda non è che il WM sia gonfio e causi un rallentamento del sistema (probabilmente risponde perfettamente in condizioni di normale utilizzo), ma che il kernel non sta correttamente dando la priorità alle applicazioni quando esaurisce la memoria e deve andare in scambio pesante. Ho riscontrato questo problema su tutti i desktop Linux che abbia mai usato e, mentre l'utilizzo di programmi più leggeri o l'aggiunta di più ram potrebbe aiutare, non risolve il problema alla radice.
crazy2be

Nel mio precedente post ho detto quanto segue: "Sembra che tu abbia alcune applicazioni che si basano su una sorta di funzione del kernel o driver che viene sovraccaricato". Quindi forse il collo di bottiglia si trova in un modulo kernel specifico. Non sono un esperto del kernel, ma sono sicuro che l'allocazione della memoria dal lato kernel, specialmente dal lato modulo, funzioni in modo diverso rispetto al lato utente. Anche l'utilizzo della CPU nel lato kernel è probabilmente gestito in modo diverso (non so se è possibile "simpatici" processi del kernel). Non posso commentare ulteriormente senza conoscere le applicazioni specifiche coinvolte.
LawrenceC,

Inoltre, se si utilizza FUSE NTFS che può causare lentezza.
LawrenceC,

1
Sono consapevole che un filesystem basato su RAM come tmpfs (ovviamente) fa sì che la RAM si esaurisca più rapidamente e che un WM leggero possa ridurre leggermente i sintomi del problema sottostante. Mi sono sentito sotto pressione per usare tmpfs a causa della scarsa reattività che la scrittura su disco può causare. Tuttavia, grazie per il tuo suggerimento, in particolare la parte relativa al DMA, che ho aggiunto all'elenco di argomenti probabilmente correlati. Per la cronaca, credo che DMA sia abilitato e non sto usando un filesystem crittografico.
user76871,

1

Questo è un problema comune con lo scheduler di Linux. Il sistema rallenta a una scansione ogni volta che si verificano attività pesanti di I / O. Non ci sono davvero molte cose che potresti fare per migliorare la situazione a meno che non ti piaccia l'hacking del kernel :)

Forse questi possono aiutare:

http://www.phoronix.com/scan.php?page=article&item=linux_2637_video&num=1

http://www.osnews.com/story/24223/Alternative_to_the_200_Lines_Kernel_Patch_that_Does_Wonders_


1
Come ricordo, quelle patch del kernel sono veramente rilevanti solo se stai compilando un programma o stai facendo qualcos'altro che è molto pesante (e IO?) In un terminale , mentre cerchi di interagire con le applicazioni della GUI. Non aiuta nella situazione più comune in cui un'applicazione GUI sta facendo un lavoro pesante e sfortunatamente stai cercando di lavorare con un'altra applicazione GUI.
crazy2be

0

Anche se la domanda ha più di due anni e la risposta di @ ypsu è ottima, la situazione con i sistemi basati su Linux sta andando male a causa della mancanza di RAM è ancora qui.

Ecco la mia osservazione sul problema: anche se non ho affatto lo scambio, una volta che il sistema è a corto di memoria, il mio indicatore del disco rigido si illumina in quanto è carico del disco al 100%. Dato questo fatto, sembra che la causa principale sia che il kernel tenta di liberare memoria scaricando qualcosa che può essere ripristinato dal disco e che, certamente, sono librerie condivise. Dato che le applicazioni della GUI di solito hanno tonnellate di librerie condivise, sembra che il sistema possa pensare che sia sufficiente scaricarne solo alcune, ma che funziona solo fino alla successiva operazione di spazio utente che richiede quelle librerie scaricate. Questo sembra essere lo scenario più probabile che causa il ciclo infinito di scaricare librerie condivise e caricarle di nuovo.

Esiste un progetto che funge da demone dello spazio utente uccidendo i processi più affamati di memoria prima che sia troppo tardi: https://github.com/rfjakob/earlyoom

Inoltre, utilizzavo i contenitori Docker con limiti di memoria sani per le applicazioni affamate di memoria (ad esempio Chrome).

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.