Eine bestimmte Datei aus dem Cache des Linux-Dateisystems löschen?

Eine bestimmte Datei aus dem Cache des Linux-Dateisystems löschen?

ich weiss ich kannalles aus dem Linux-Dateisystem-Cache löschen, aber gibt es eine Möglichkeit, nur eine bestimmte Datei zu löschen? Oder zu verhindern, dass eine Datei zwischengespeichert wird? Oder einem Prozess mitzuteilen, dass er keine Dateien zwischenspeichern soll, die er schreibt?

Ich habe einen Prozess, der viele kleine Dateien liest und eine große Datei schreibt. Ich möchte die kleinen Dateien im Cache behalten, um Suchvorgänge auf der Festplatte zu vermeiden, und das Zwischenspeichern der großen Datei ist mir egal.

Antwort1

Mögliche Methode Nr. 1 – F_DROP_CACHES

Ich habe in diesem E-Mail-Thread mit dem Titel eine Methode aus dem Jahr 2012 gefunden, in der ein vorgeschlagener Patch für den Linux-Kernel diskutiert wird:Betreff: [RFC Patch] fs: Implementierung von Drop-Caches pro Datei.

Auszug

Cong> Dies ist ein Patch-Entwurf zur Implementierung von Drop-Caches pro Datei.

Interessant. Kann ich das also von außerhalb eines Prozesses tun? Ich bin ein Systemadministrator, daher besteht mein Standpunkt darin, Leistungsprobleme zu erkennen, zu finden und zu beheben, wenn das System unter Druck steht.

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.

Wie kann ich feststellen, wie viel Cache von einer Datei verwendet wird? Und welche Auswirkungen hat dies auf die Leistung, wenn es auf einem ausgelasteten System ausgeführt wird? Und was bringt uns dieser Patch, da ich davon ausgehe, dass die VM bereits Caches löschen sollte, sobald das System unter Speicherdruck gerät ...

Cong> Unten ist ein kleiner Testfall für diesen Patch:

Der Thread enthält sowohl einen Testfall als auch den eigentlichen Patch für mehrere Dateien im Linux-Kernel, der eine zusätzliche Funktion namens hinzufügt fs/drop_caches.c. drop_pagecache_file(struct file *filp)Auf diese Funktion kann dann über das Frontend-Tool fnctl.cmit dem Befehl zugegriffen werden F_DROP_CACHES. In diesem Fall wird diese Funktion aufgerufen:

file_drop_caches(filp, arg);

Dadurch werden alle Caches gelöscht, die mit der angegebenen Datei verknüpft sind. Aus der Datei include/linux/mm.h:

void file_drop_caches(struct file *filp, unsigned long which);
Kann das also verwendet werden?

Ich habe keine Hinweise darauf gefunden, dass dieser Patch jemals den Weg in das Haupt-Code-Repository des Linux-Kernels gefunden hat. Daher scheint diese Option nur verfügbar zu sein, wenn Sie bereit sind, den Linux-Kernel selbst neu zu kompilieren.

Mögliche Methode Nr. 2 – Verwenden von dd

Im selben Thread erwähnt ein anderer Benutzer eine völlig andere Methodik, die verwendet dd.

Nachfolgend ein Auszugaus dieser E-Mail

Dies ist eine nützliche Funktion. Aber ist sie nicht bereits in enthalten POSIX_FADV_DONTNEED? Diese Funktion wurde hinzugefügt zuGNU dd (8.11) vor einem Jahr.

Hier sind die Beispiele aus diesem Patch:
  • Empfehlung, den Cache für die gesamte Datei zu löschen

     $ dd if=ifile iflag=nocache count=0
    
  • Stellen Sie sicher, dass der Drop-Cache für die gesamte Datei

     $ dd of=ofile oflag=nocache conv=notrunc,fdatasync count=0
    
  • Cache für einen Teil der Datei löschen

     $ dd if=ifile iflag=nocache skip=10 count=10 of=/dev/null
    
  • Daten nur mit dem Read-Ahead-Cache streamen

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

Ich war nicht 100 % sicher, wie ich das testen sollte, aber mir kam der folgende Ansatz.

  1. Erstellen Sie eine 100 MB große Datei

    $ dd if=/dev/urandom of=sample.txt bs=100M count=1
    
  2. Trace-Dateizugriffe mitfatrace

    $ sudo fatrace | grep sample.txt
    
  3. Führen Sie es aus top, damit wir die Speichernutzung überwachen und die freie Menge notieren können.

    $ top
    
  4. Öffnen Sie die Datei und notieren Sie sich die Menge des jetzt freien Speichers. Notieren Sie sich den fatraceWert der Datei sample.txt.

    $ cat sample.txt > /dev/null
    
  5. Löschen Sie die Datei aus dem Speicher. Notieren Sie sich die Menge des jetzt freien Speichers. Notieren Sie sich die Ausgabe von fatrace.

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

Beispiel

Im Terminal Nr. 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
Im Terminal Nr. 2:
$ top
...
KiB Mem:   7968336 total,  6900956 used,  1067380 free,   267080 buffers
...
Im Terminal Nr. 3:
$ sudo fatrace | grep sample.txt
Öffnen Sie nun die Datei sample.txtund notieren Sie sich die RAM-Menge. Im Terminal Nr. 1.
$ cat sample.txt > /dev/null
Im Terminal Nr. 2:
KiB Mem:   7968336 total,  7011896 used,   956440 free,   267336 buffers
Beachten Sie die Ausgabe fatraceim Terminal Nr. 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
Entfernen Sie nun die Datei aus dem RAM im Terminal Nr. 4:
$ sudo dd of=/home/saml/tst/162600/sample.txt \
    oflag=nocache conv=notrunc,fdatasync count=0
Beachten Sie die Ausgabe fatraceim Terminal Nr. 2:
dd(26229): O /home/saml/tst/162600/sample.txt
dd(26229): CW /home/saml/tst/162600/sample.txt
Beachten Sie den RAM in Terminal Nr. 3:
KiB Mem:   7968336 total,  6908364 used,  1059972 free,   267364 buffers

Es scheint also, dass der gesamte von der Datei verbrauchte RAM freigegeben wird.

Mögliche Methode Nr. 3 - python-fadvise

Dank eines Kommentars von @frostchutz gibt es ein weiteres Tool, ein Python-Skript namens , [pyadvise][4]das eine viel einfachere Schnittstelle als die oben genannten ddMethoden bietet. Dieses Skript verwendet dieselbe posix_fadvise(2)Schnittstelle.

Beispiel
$ 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

Und wenn wir den obigen Test wiederholen und pyadviseanstelle von verwenden dd:

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

Mir ist ein identischer Rückgang beim RAM-Verbrauch aufgefallen wie zuvor, als ich verwendet habe dd.

Antwort2

Wenn Sie die Antwort von @geekosaur erweitern, können Sie die Verwendung von erzwingen, O_DIRECTindem Sie LD_PRELOAD und das Programm hier verwenden:http://arighi.blogspot.com/2007/04/how-to-bypass-buffer-cache-in-linux.html

Dieser Code wird für alle Dateien erzwungen . Sie können O_DIRECT O_DIRECTjedoch selektiv anwenden, indem Sie einfach etwas mehr Strncmp-Logik hinzufügen .__do_wrap_open

Haftungsausschluss: Ich habe dies nicht getestet.

Antwort3

Sie können einzelne Dateien mit der Flagge öffnen O_DIRECT(siehe man 2 open) – lesen Sie dieANMERKUNGENdieser Manpage sorgfältig durch und überlegen Sie, ob Sie auch wollen/brauchen O_SYNC.

Antwort4

Wenn Sie eine Datei zwingen möchten, immer O_SYNC zu verwenden, können Sie dies in den erweiterten Attributen wie folgt markieren chattr +S $file:

Mann chattr:

Wenn eine Datei mit dem Attributsatz „S“ geändert wird, werden die Änderungen synchron auf die Festplatte geschrieben. Dies entspricht der Mount-Option „sync“, die auf eine Teilmenge der Dateien angewendet wird.

O_SYNC erzwingt das Schreiben der Daten und Metadaten in die Festplattenpuffer, durchläuft dabei aber dennoch den Seitencache. O_DIRECT umgeht den Seitencache.

Beachten Sie jedoch, dass das Öffnen mit O_DIRECT die Leistung beeinträchtigen würde. Wenn die große Datei nur angehängt wird, ist der Unterschied möglicherweise gering. Wenn die große Datei jedoch an zufälligen Stellen neu geschrieben wurde, wird O_DIRECT die Leistung erheblich beeinträchtigen, selbst wenn berücksichtigt wird, dass durch die Anwesenheit im Cache möglicherweise einige der kleinen Lesedateien aus dem Cache entfernt werden könnten.

Wenn Sie genug RAM haben, um alle kleinen Dateien dort zu speichern, können Sie das Problem auch andersherum angehen. Stellen Sie sicher, dass die kleinen Dateien immer im RAM sind, dann würde ich vorschlagen, sie zu kopieren nachtmps:

tmpfs legt alles in die internen Caches des Kernels und vergrößert bzw. verkleinert sich, um Platz für die darin enthaltenen Dateien zu schaffen

verwandte Informationen