Eliminare un file specifico dalla cache del filesystem Linux?


23

So di poter eliminare tutto dalla cache del filesystem Linux , ma c'è un modo per eliminare solo un file specifico? O impedire la memorizzazione nella cache di un file? O dire a un processo di non memorizzare nella cache i file che scrive?

Ho un processo che legge molti piccoli file e scrive un grosso file. Voglio mantenere i piccoli file nella cache per evitare la ricerca del disco e non mi interessa memorizzare nella cache il file di grandi dimensioni.


1
Per quanto riguarda la generosità, sono particolarmente interessato alla domanda sul titolo: eliminare un file specifico dalla cache (anziché impedirgli di arrivarci in primo luogo).
Gilles 'SO- smetti di essere malvagio' il

Risposte:


21

Metodo potenziale n. 1 - F_DROP_CACHES

Ho trovato un metodo dal 2012 che discute una patch proposta per il kernel Linux in questo thread di posta intitolato: Re: [Patch RFC] fs: implementa cache di rilascio per file .

estratto

Cong> Questa è una bozza di patch per l'implementazione delle cache di rilascio per file.

Interessante. Quindi posso farlo dall'esterno di un processo? Sono un Amministratore di sistema, quindi il mio punto di vista è di notare, trovare e risolvere i problemi di prestazioni quando il sistema è sotto pressione.

Cong> It introduces a new fcntl command  F_DROP_CACHES to drop  
Cong> file caches of a specific file. The reason is that currently  
Cong> we only have a system-wide drop caches interface, it could  
Cong> cause system-wide performance down if we drop all page caches  
Cong> when we actually want to drop the caches of some huge file.

Come posso sapere quanta cache viene utilizzata da un file? E qual è l'impatto sulle prestazioni di questo quando eseguito su un sistema occupato? E cosa ci offre questa patch dal momento che immagino che la VM dovrebbe già aver lasciato cadere le cache una volta che il sistema è sotto pressione dei mem ...

Cong> Di seguito è riportato un piccolo test case per questa patch:

Il filo include sia un testcase e la patch reale per diversi file all'interno del kernel di Linux che aggiunge una funzione supplementare a fs/drop_caches.cchiamata drop_pagecache_file(struct file *filp). Questa funzione è quindi accessibile tramite lo strumento frontend, fnctl.ctramite il comando F_DROP_CACHES. Questo caso chiama questa funzione:

file_drop_caches(filp, arg);

Che gestisce il rilascio di tutte le cache associate al file specificato. Dal file include/linux/mm.h:

void file_drop_caches(struct file *filp, unsigned long which);
Quindi questo può essere usato?

Non ho trovato prove che questa patch sia mai entrata nel principale repository di codice del kernel Linux, quindi questa opzione sembrerebbe essere disponibile, solo se sei disposto a ricompilare tu stesso il kernel Linux.

Metodo potenziale n. 2 - Utilizzo di dd

Nello stesso thread, un altro utente menziona una metodologia completamente diversa che utilizza dd.

Quello che segue è estratto da quell'email

Questa è una funzionalità utile. Sebbene non sia già fornito POSIX_FADV_DONTNEED? Questa funzionalità è stata aggiunta a GNU dd (8.11) un anno fa .

Ecco gli esempi di quella patch:
  • Consiglia di eliminare la cache per l'intero file

     $ dd if=ifile iflag=nocache count=0
    
  • Assicurati di eliminare la cache per l'intero file

     $ dd of=ofile oflag=nocache conv=notrunc,fdatasync count=0
    
  • Elimina la cache per parte del file

     $ dd if=ifile iflag=nocache skip=10 count=10 of=/dev/null
    
  • Streaming dei dati utilizzando solo la cache read-ahead

     $ dd if=ifile of=ofile iflag=nocache oflag=nocache
    
Provandolo

Non ero sicuro al 100% su come testarlo, ma ho trovato il seguente approccio.

  1. crea un file da 100 MB

    $ dd if=/dev/urandom of=sample.txt bs=100M count=1
    
  2. tracciare gli accessi ai file usando fatrace

    $ sudo fatrace | grep sample.txt
    
  3. eseguire in topmodo che possiamo monitorare l'utilizzo della memoria, nota quantità gratuita.

    $ top
    
  4. apri il file, nota la quantità di memoria libera ora. Nota fatraceil file sample.txt.

    $ cat sample.txt > /dev/null
    
  5. rilascia il file dalla memoria, nota subito la quantità di memoria libera. Nota l'output di fatrace.

    $ sudo dd of=/home/saml/tst/162600/sample.txt \
        oflag=nocache conv=notrunc,fdatasync count=0
    

Esempio

Nel terminale n. 1:
$ dd if=/dev/urandom of=sample.txt bs=100M count=1
1+0 records in
1+0 records out
104857600 bytes (105 MB) copied, 7.37996 s, 14.2 MB/s

$ ls -l sample.txt 
-rw-rw-r--. 1 saml saml 104857600 Oct 17 22:54 sample.txt
Nel terminal 2:
$ top
...
KiB Mem:   7968336 total,  6900956 used,  1067380 free,   267080 buffers
...
Nel terminal 3:
$ sudo fatrace | grep sample.txt
Ora apri il file sample.txte osserva la quantità di RAM. Nel terminale n. 1.
$ cat sample.txt > /dev/null
Nel terminal 2:
KiB Mem:   7968336 total,  7011896 used,   956440 free,   267336 buffers
Notare l'output del fatraceterminale n. 3:
cat(25940): R /home/saml/tst/162600/sample.txt
cat(25940): R /home/saml/tst/162600/sample.txt
cat(25940): RC /home/saml/tst/162600/sample.txt
Ora rimuovi il file dalla RAM, nel terminale # 4:
$ sudo dd of=/home/saml/tst/162600/sample.txt \
    oflag=nocache conv=notrunc,fdatasync count=0
Notare l'uscita di fatracenel terminale # 2:
dd(26229): O /home/saml/tst/162600/sample.txt
dd(26229): CW /home/saml/tst/162600/sample.txt
Notare la RAM nel terminale n. 3:
KiB Mem:   7968336 total,  6908364 used,  1059972 free,   267364 buffers

Quindi sembrerebbe che tutto ciò che è stato consumato dal file nella RAM sia stato liberato.

Metodo potenziale n. 3 - python-fadvise

Grazie a un commento di @frostchutz, c'è un altro strumento, uno script Python, chiamato [pyadvise][4]che fornisce un'interfaccia molto più semplice rispetto ai ddmetodi di cui sopra . Questo script utilizza la stessa posix_fadvise(2)interfaccia.

Esempio
$ sudo pyadvise --help
Usage: 
    pyadvise [options] [FILE]..

Options:
  -h, --help        show this help message and exit
  -w, --willneed    The specified files will be accessed in the near future
  -s, --sequential  The application expects to access the specified files
                    sequentially (with lower offsets read before higher ones)
  -d, --dontneed    The specified files will not be accessed in the near
                    future
  -r, --random      The specified files will be accessed in random order
  -o, --noreuse     The specified files will be accessed only once. Under
                    Linux, this operation is a no-op; see contrib/copyfileobj-
                    fadvise.py in the python-fadvise source tree for an
                    example on how to achieve approximately the same effect
  -n, --normal      Indicates that the application has no advice to give about
                    its access pattern for the specified files. If no advice
                    is given for an open file, this is the default assumption
  -v, --verbose     Explain what is being done

E se ripetiamo il test sopra e utilizziamo pyadviseal posto di dd:

$ pyadvise -d /home/saml/tst/162600/sample.txt

Ho notato un calo identico nella RAM consumato come prima quando l'ho usato dd.


ddper me va bene. Ho finito con chris-lamb.co.uk/projects/python-fadvise me stesso che è la stessa cosa in un comando più ovvio.
frostschutz,

@frostschutz - molto bello. Non ne avevo sentito parlare fino a quando Gilles non mi ha chiesto se qualcuno sapeva come farlo in chat. python-fadviseè molto più semplice, ho aggiunto un esempio che mostra dd.
slm

Il collegamento per lo script Python dovrebbe essere spostato nel corpo principale della domanda. I commenti possono scomparire senza lasciare traccia. Nel peggiore dei casi una modifica rimarrà nella storia. Detto questo, una ricerca su Google lo trova facilmente, quindi non è un grosso problema.
Faheem Mitha,

Sembra anche che funzioni senza sudo, quindi chiunque può vedere un file (anche senza permesso di scrittura) può far cadere la cache, questo è ... interessante.
frostschutz,

1
os.posix_fadvise()Ora c'è nel libray standard di Python.
kawing-chiu,


2

Puoi aprire singoli file con il O_DIRECTflag (vedi man 2 open) - leggi attentamente la sezione NOTE di quella pagina man e considera se anche tu vuoi / hai bisogno O_SYNC.


1
Bene, il mio processo è cat, e preferirei non riscriverlo. :) Speravo in uno strumento da riga di comando o in una /proc/sysmanopola.
Jay Hacker,

2
Peggio ancora, sospetto che tu intenda davvero che stai usando il reindirizzamento, quindi il tuo processo è la shell. Non conosco un modo per file per controllare questo a parte la openbandiera; avresti davvero bisogno di scrivere un programma per farlo. ( cat -udisabilita solo il stdiobuffering, non il buffering del sistema operativo.)
geekosaur

-2

Se si desidera forzare un file a utilizzare sempre O_SYNC, è possibile contrassegnarlo come tale negli attributi estesi con chattr +S $file:

man chattr:

Quando viene modificato un file con l'attributo 'S' impostato, le modifiche vengono scritte in modo sincrono sul disco; questo equivale all'opzione di montaggio 'sync' applicata a un sottoinsieme dei file.

O_SYNC impone che i dati + i metadati vengano scritti nei buffer del disco, ma passa comunque attraverso la cache della pagina. O_DIRECT ignora la cache della pagina.

Ma tieni presente che aprirlo con O_DIRECT sarebbe dannoso per le prestazioni, se il file di grandi dimensioni viene appena aggiunto la differenza potrebbe essere piccola. Ma se il file di grandi dimensioni è stato riscritto in punti casuali, O_DIRECT sarà un grande successo in termini di prestazioni, anche tenendo conto del fatto che averlo nella cache potrebbe eventualmente eliminare dalla cache alcuni dei piccoli file letti.

Se hai il ram per mantenere lì tutti i file di piccole dimensioni, potresti affrontare il problema in altro modo. Assicurati che i piccoli file siano sempre in ram, quindi suggerirei di copiarli in tmpfs :

tmpfs inserisce tutto nella cache interna del kernel e cresce e si restringe per adattarsi ai file che contiene


chattr +Snon è la stessa cosa di O_DIRECT, è la stessa cosa di O_SYNC. O_DIRECTfa sì che le letture non vengano memorizzate nella cache (che è ciò di cui tratta questa domanda) e le scritture non vengono memorizzate nel buffer, senza alcuna garanzia. O_SYNCfa sì che solo le scritture non vengano bufferizzate.
Gilles 'SO- smetti di essere malvagio' il

@Gilles hai ragione, ho letto la domanda e ho pensato di scaricare i dati sul disco come avevo fatto prima. E c'è un altro sottile, ma importante in questo caso, la differenza tra O_DIRECT e O_SYNC, O_DIRECT ignora la cache della pagina, ma O_SYNC no, forza i dati (e i metadati) per essere scaricati sul disco, ma passa attraverso la cache della pagina e viene tenuto lì per accelerare le letture. Dovrei cambiare O_DIRECT per O_SYNC nella mia risposta per non lasciarlo con un'affermazione sbagliata?
Jorge Nerín,

Questa domanda chiede come mantenere un file di grandi dimensioni che è stato scritto dalla cache. Penso che aprirlo con O_DIRECT sarebbe dannoso per le prestazioni, e se il file di grandi dimensioni viene appena aggiunto, la differenza potrebbe essere piccola. Ma se il file di grandi dimensioni è stato riscritto in punti casuali, O_DIRECT sarà un grande successo in termini di prestazioni, anche tenendo conto del fatto che potrebbe eventualmente eliminare dalla cache alcuni dei piccoli file letti.
Jorge Nerín,

Cambiare O_DIRECTin O_SYNCrenderebbe la tua risposta internamente coerente, ma comunque sbagliata considerando la domanda.
Gilles 'SO- smetti di essere malvagio' il
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.