Forza la directory sempre nella cache


35

Ho testato diversi metodi per migliorare il tempo necessario per compilare il mio intero progetto c ++. Attualmente ci vogliono circa 5 minuti. Ho sperimentato con distcc, ccache e altri. Di recente, ho scoperto che se copio il mio intero progetto su un'unità RAM, e poi compilo da lì, riduce il tempo di compilazione fino al 30% del suo originale - solo 1,5 minuti.

Ovviamente, lavorare dall'unità RAM non è pratico. Quindi, qualcuno conosce un modo in cui posso forzare il sistema operativo a mantenere sempre nella cache una determinata directory ? Voglio ancora che la directory venga sincronizzata su disco come al solito, ma voglio sempre anche una copia dei dati in memoria. È possibile?

EDIT: Come possibile soluzione, abbiamo appena pensato di avviare un demone che viene eseguito rsyncogni 10 secondi circa per sincronizzare l'unità disco con un'unità RAM. Quindi eseguiamo la compilation dall'unità RAM. È rsyncvelocissimo, ma funzionerebbe davvero? Sicuramente il sistema operativo potrebbe fare di meglio ....


La cache non è l'unica differenza tra tmpfs ed ext3 / 4; hanno un journaling, ad esempio, che verrà scritto indipendentemente dalla memorizzazione nella cache.
André Paramés,

1
Potresti la timetua compilation e condividere il risultato con noi? Dissolverebbe alcune controversie sollevanti. make clean && /usr/bin/time -v make(non usare il timecomando incorporato bash )
shellholic

1
@she Perché non il comando integrato di bash?
Tshepang,

3
@Tshepang il timebuilt in bash ( help time) ha molti meno dettagli (nessuna opzione dettagliata) rispetto al tempo GNU ( man time) riguardante l'I / O, i cambi di contesto, ...
shellholic

Risposte:


18

Il modo ovvio per mantenere un mucchio di file nella cache è di accedervi spesso. Linux è abbastanza bravo nell'arbitrare tra scambio e memorizzazione nella cache, quindi sospetto che la differenza di velocità che osservi non sia in realtà dovuta al fatto che il sistema operativo non tiene le cose nella cache, ma a qualche altra differenza tra l'uso di tmpfs e altri tuoi tentativi.

Prova ad osservare cosa sta facendo IO in ogni caso. Lo strumento di base è quello iotop. Altri strumenti possono essere utili; vedi la ripartizione del carico IO del disco Linux, per percorso del file system e / o processo? , Quale programma in Linux può misurare l'I / O nel tempo? e altri thread in Server Fault.

Ecco alcune ipotesi su cosa potrebbe accadere. Se prendi le misure, mostrale in modo che possiamo confermare o confutare queste ipotesi.

  • Se i tempi di accesso ai file sono attivati, il sistema operativo potrebbe perdere parecchio tempo a scrivere questi tempi di accesso. I tempi di accesso sono inutili per un albero della compilation, quindi assicurati che siano disattivati ​​con l' noatimeopzione mount. La tua soluzione tmpfs + rsync non legge mai dal disco rigido, quindi non deve mai perdere altro tempo a scrivere atimes.
  • Se le scritture si stanno sincronizzando , sia perché il compilatore chiama sync()o perché il kernel scarica frequentemente i suoi buffer di output, le scritture impiegheranno più tempo su un disco rigido che su tmpfs.

Anch'io ho questa sensazione. La compilazione richiede molta CPU, anziché IO.
phunehehe,

Hmmm, mi piacerebbe vedere un commento di @JaredC qui che conferma o smentisce l'ipotesi di Gilles. 1,5 contro 5 minuti è una grande differenza ...
Daniel Alder

8

Linux per impostazione predefinita usa la RAM come cache del disco. Come dimostrazione, prova a eseguire time find /some/dir/containing/a/lot/of/files > /dev/nulldue volte, la seconda volta è molto più veloce in quanto tutti gli inode del disco vengono memorizzati nella cache. Il punto qui è come utilizzare questa funzionalità del kernel e fermare il tentativo di sostituirla.

Il punto è cambiare il swappiness. Consideriamo tre tipi principali di utilizzo della memoria: programmi attivi, programmi inattivi e cache del disco. Ovviamente la memoria utilizzata dai programmi attivi non dovrebbe essere scambiata e la scelta tra due altri è abbastanza arbitraria. Desideri passare rapidamente da un programma all'altro o accedere rapidamente ai file? Una bassa swapiness preferisce mantenere i programmi in memoria (anche se non utilizzati per lungo tempo) e una elevata swapiness preferisce mantenere più cache del disco (scambiando programmi inutilizzati). (la scala di scambio va da 0 a 100 e il valore predefinito è 60)

La mia soluzione al tuo problema è di cambiare lo swappiness su molto alto (90-95 per non dire 100) e caricare la cache:

echo 95 | sudo tee /proc/sys/vm/swappiness > /dev/null # once after reboot
find /your/source/directory -type f -exec cat {} \; > /dev/null

Come indovinate, è necessario disporre di memoria sufficiente per contenere nella cache tutti i file di origine e file oggetto, nonché il compilatore, i file di intestazioni inclusi, le librerie collegate, l'IDE e altri programmi utilizzati.


Questo è utile in generale, ma quello che voglio davvero è che il mio codice sorgente abbia una bassa swappiness, ma tutto il resto ha una normale swappiness. In sostanza, ho molte cose in corso in background, ma voglio limitarle a 6 su 8 GB, mantenendo sempre gli altri 2 GB per il codice sorgente. Non voglio correre il rischio che venga scambiato ... mai ... perché è fastidioso.
JaredC,

Swappiness è a livello di sistema. Infatti se stai facendo qualcos'altro e i tuoi file vengono scaricati dalla memoria, devi solo ricaricarlo con la seconda riga. Se la memoria deve essere liberata per qualcos'altro, in realtà non si "vuole correre il rischio" che venga fatto dallo scambio. A proposito, tmpfsnello stesso caso verrebbe anche sostituito.
Shellholic

2
Personalmente sono caduto in alto lo swappiness è assolutamente orribile sulle stazioni di lavoro. Sebbene alcune funzioni potrebbero essere accelerate dalla cache più grande (ovvero più file memorizzati nella cache), ciò ha un prezzo: si paga in termini di reattività quando si passa da un programma all'altro, che è ciò che gli utenti notano per primi quando lavorano su un sistema. Quando si passa da browser a ufficio a un altro browser a e-mail, non riesco proprio a dover aspettare 1-2 secondi per far tornare indietro ogni programma. Su tutte le mie macchine linux generalmente lo swappiness ha un valore basso di 10.
fgysin ripristina Monica il

6

Forzare la cache non è il modo giusto per farlo. Meglio mantenere le fonti sul disco rigido e compilarle su tmpfs. Molti sistemi di build, come qmake e CMake, supportano build out-of-source.


6

Il inosyncdemone sembra fare esattamente quello che vuoi se hai intenzione di risincronizzare su un ramdisk. Invece di risincronizzare ogni 10 secondi circa, usa la funzione di inotify di Linux per risincronizzare quando un file cambia. L'ho trovato nel repository Debian come inosyncpacchetto, oppure la sua fonte è disponibile su http://bb.xnull.de/projects/inosync/ .


Sembra abbastanza utile. Lo esaminerò e riferirò indietro. Grazie!
JaredC,

5

Questa cosa sembra funzionare per me se voglio mantenere determinati file o tutti i file in una determinata directory nella cache.

vmtouch sembra fare la cosa giusta. Esempio 5 potrebbe esserci quello che ti serve.

vmtouch -dl /whatever/directory/

Avevo bisogno di eseguirlo come root con sudo


1
Non vede i file nuovi / rimossi.
Vi.

3

Data la memoria sufficiente, il tuo build fuori dal ramdisk non ha I / O. Questo può accelerare tutto ciò che legge o scrive file. L'I / O è una delle operazioni più lente. Anche se tutto viene memorizzato nella cache prima della compilazione, si hanno ancora gli I / O per la scrittura, anche se dovrebbero avere un impatto minimo.

È possibile ottenere un po 'di velocità pre-caricando tutti i file nella cache, ma il tempo impiegato dovrebbe essere incluso nei tempi di compilazione totali. Questo potrebbe non darti molto vantaggio.

Creazione dell'oggetto e file intermedi nella RAM anziché nel disco. Fare build incrementali può farti ottenere guadagni significativi su build frequenti. Sulla maggior parte dei progetti faccio una build pulita giornaliera e build incrementali in mezzo. Le build di integrazione sono sempre build pulite, ma provo a limitarle a meno di una al giorno.

È possibile ottenere alcune prestazioni utilizzando una partizione ext2 con atime disattivato. Il tuo sorgente dovrebbe essere nel controllo di versione su un file system journaled come ext3 / 4.


2

Come affermato in precedenza, il modo più ovvio è leggere tutta la struttura delle directory e i contenuti dei file di ciò che si desidera memorizzare nella cache.

Puoi automatizzarlo scrivendo uno script per monitorare l'output di vmstat 1(usa qualsiasi strumento equivalente per il tuo sistema operativo) e mantenere una somma del numero di blocchi scritti e letti. Una volta che la somma supera una soglia di tua scelta, leggi tutti i file che intendi memorizzare nella cache, reimposta la somma, quindi continua a monitorare l'output di vmstat. Per leggere rapidamente i file: se il tuo albero contiene molti file, evita find ... -exec catinvece di provare find ... -print0 | xargs -0 cato un programma personalizzato che non eseguirà cat per ogni file.

Il monitoraggio dell'IO del disco è preferibile all'uso di un intervallo fisso perché segnala di rileggere i dati più o meno frequentemente a seconda del carico dell'IO del disco.

Ho usato questo metodo automatizzato con successo su sistemi in cui avevo bisogno che alcune letture dei file di indice fossero sempre veloci, evitando l'I / O del disco rigido. Ho anche usato strace per creare un elenco di tutti i file a cui accedo quando eseguo l'accesso in modo da poter tenere tutto caldo nella cache per accessi veloci.

Questa potrebbe non essere la migliore soluzione possibile, ma mi andava bene.

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.