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

23

Ich weiß, dass ich alles aus dem Linux-Dateisystem-Cache löschen kann , aber gibt es eine Möglichkeit, nur eine bestimmte Datei zu löschen? Oder verhindern, dass eine Datei zwischengespeichert wird? Oder weisen Sie einen Prozess an, keine Dateien zwischenzuspeichern, 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 Festplatten-Suchvorgänge zu vermeiden, und es ist mir egal, ob ich die große Datei zwischenspeichere.

Jay Hacker
quelle
1
In Bezug auf das Kopfgeld interessiert mich insbesondere die Titelfrage: Löschen einer bestimmten Datei aus dem Cache (anstatt zu verhindern, dass sie überhaupt dort ankommt).
Gilles 'SO - hör auf, böse zu sein'

Antworten:

21

Mögliche Methode # 1 - F_DROP_CACHES

Ich habe eine Methode aus dem Jahr 2012 gefunden, die einen vorgeschlagenen Patch für den Linux-Kernel in diesem E-Mail-Thread mit dem Titel: Re: [RFC-Patch] fs: Implementiere Drop-Caches pro Datei .

Auszug

Cong> Dies ist ein Entwurfspatch zum Implementieren von Drop-Caches pro Datei.

Interessant. Kann ich das also außerhalb eines Prozesses tun? Ich bin ein SysAdmin. Mein POV besteht also darin, Leistungsprobleme zu bemerken, 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 wie wirkt sich dies auf die Leistung aus, wenn das System ausgelastet ist? Und was bringt uns dieser Patch, da ich der Meinung bin, dass die VM bereits Caches löschen sollte, wenn das System unter Mem-Druck gerät ...

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

Der Faden umfasst sowohl einen Testfall und die aktuelle Patch auf mehrere Dateien innerhalb des Linux - Kernels, die eine zusätzliche Funktion fügt fs/drop_caches.cgenannt drop_pagecache_file(struct file *filp). Diese Funktion ist dann über das Frontend-Tool fnctl.cüber den Befehl zugänglich F_DROP_CACHES. Dieser Fall ruft diese Funktion auf:

file_drop_caches(filp, arg);

Welches behandelt das Löschen aller Caches, die mit der angegebenen Datei verbunden sind. Aus der Datei include/linux/mm.h:

void file_drop_caches(struct file *filp, unsigned long which);
Das kann also genutzt werden?

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

Mögliche Methode 2 - Verwenden von dd

In demselben Thread erwähnt ein anderer Benutzer eine völlig andere Methodik, die verwendet wird dd.

Das Folgende ist ein Auszug aus dieser E-Mail

Dies ist eine nützliche Funktion. Obwohl es nicht bereits mit versehen ist POSIX_FADV_DONTNEED? Diese Funktionalität wurde vor einem Jahr zu GNU dd (8.11) hinzugefügt .

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

     $ dd if=ifile iflag=nocache count=0
    
  • Stellen Sie sicher, dass der Cache für die gesamte Datei gelöscht wird

     $ 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
    
  • Streamen Sie Daten nur mit dem Read-Ahead-Cache

     $ dd if=ifile of=ofile iflag=nocache oflag=nocache
    
Testen Sie es aus

Ich war nicht zu 100% sicher, wie ich das testen sollte, aber ich kam auf den folgenden Ansatz.

  1. Erstellen Sie eine 100-MB-Datei

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

    $ sudo fatrace | grep sample.txt
    
  3. Laufen Sie, topdamit wir die Speichernutzung überwachen können.

    $ top
    
  4. Datei öffnen, Speicherplatz jetzt merken. Beachten Sie die fatraceder Datei sample.txt.

    $ cat sample.txt > /dev/null
    
  5. Löschen Sie die Datei aus dem Speicher und notieren Sie sich den freien Speicherplatz. Beachten Sie die Ausgabe von fatrace.

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

Beispiel

Im Terminal 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 2:
$ top
...
KiB Mem:   7968336 total,  6900956 used,  1067380 free,   267080 buffers
...
Im Terminal 3:
$ sudo fatrace | grep sample.txt
Öffnen Sie nun die Datei sample.txtund notieren Sie die Größe des Arbeitsspeichers. Im Terminal Nr. 1.
$ cat sample.txt > /dev/null
Im Terminal 2:
KiB Mem:   7968336 total,  7011896 used,   956440 free,   267336 buffers
Beachten Sie die Ausgabe von fatracein Terminal 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 in Terminal 4:
$ sudo dd of=/home/saml/tst/162600/sample.txt \
    oflag=nocache conv=notrunc,fdatasync count=0
Beachten Sie die Ausgabe von fatracein Terminal # 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 3:
KiB Mem:   7968336 total,  6908364 used,  1059972 free,   267364 buffers

Es scheint also, dass alles, was von der Datei im RAM verbraucht wurde, freigegeben wird.

Mögliche Methode # 3 - Python-Fadvise

Dank eines Kommentars von @frostchutz gibt es ein anderes Tool, ein Python-Skript mit dem Namen [pyadvise][4], das eine viel einfachere Oberfläche 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 dd:

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

Ich bemerkte einen identischen Abfall des RAM, der wie vorher verbraucht wurde, als ich benutzte dd.

slm
quelle
ddfunktioniert bei mir. Ich landete mit chris-lamb.co.uk/projects/python-fadvise mir was dasselbe in einem offensichtlicher Befehl ist.
Frostschutz
@frostschutz - sehr cool. Ich hatte nichts davon gehört, bis Gilles fragte, ob jemand wüsste, wie man das im Chat macht. python-fadviseist viel einfacher, ich habe ein Beispiel hinzugefügt dd.
SLM
Der Link für das Python-Skript sollte in den Hauptteil der Frage verschoben werden. Kommentare können spurlos verschwinden. Eine Bearbeitung wird schlimmstenfalls noch in der Geschichte bleiben. Allerdings findet eine Google-Suche es leicht, also keine große Sache.
Faheem Mitha
Es scheint sogar ohne sudo zu funktionieren, so dass jeder, der eine Datei sehen kann (auch ohne Schreibberechtigung), den Cache löschen kann, das ist ... interessant.
Frostschutz
1
Es ist os.posix_fadvise()jetzt in Pythons Standard-Libray.
Kawing-Chiu
3

Wenn Sie die Antwort von @geekosaur erweitern, können Sie die Verwendung 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 gilt O_DIRECTfür alle Dateien. Wenn __do_wrap_openSie jedoch einfach etwas mehr strncmp-Logik hinzufügen, können Sie O_DIRECT selektiv anwenden.

Haftungsausschluss: Ich habe dies nicht getestet.

Mark Wagner
quelle
2

Sie können einzelne Dateien mit dem O_DIRECTFlag öffnen (siehe man 2 open) - lesen Sie den Abschnitt NOTES auf dieser Manpage sorgfältig durch und überlegen Sie, ob Sie auch möchten / brauchen O_SYNC.

Geekosaurier
quelle
1
Nun, mein Prozess ist catund ich möchte ihn lieber nicht umschreiben. :) Ich hatte auf ein Kommandozeilen-Tool oder einen /proc/sysKnopf gehofft .
Jay Hacker
2
Schlimmer noch, ich vermute, Sie meinen wirklich, dass Sie die Umleitung verwenden, also ist Ihr Prozess die Shell. Ich kenne keine Möglichkeit, dies pro Datei zu steuern, abgesehen von der openFlagge. Sie müssten in der Tat ein Programm schreiben, um es zu tun. ( cat -ustdio
Deaktiviert
-2

Wenn Sie eine Datei zwingen möchten, immer O_SYNC zu verwenden, können Sie sie in den erweiterten Attributen folgendermaßen kennzeichnen chattr +S $file:

Mann Chattr:

Wenn eine Datei mit dem Attribut "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 + Metadaten in die Plattenpuffer, durchläuft jedoch weiterhin den Seitencache. O_DIRECT umgeht den Seiten-Cache.

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 einer zufälligen Stelle neu geschrieben wird, wird O_DIRECT die Leistung erheblich beeinträchtigen, auch wenn berücksichtigt wird, dass sie möglicherweise im Cache gespeichert ist und einige der kleinen gelesenen Dateien aus dem Cache entfernt werden können.

Wenn Sie den RAM haben, um alle kleinen Dateien dort zu speichern, können Sie das Problem auf die andere Weise angehen. Stellen Sie sicher, dass die kleinen Dateien immer im RAM sind, dann würde ich vorschlagen, sie nach tmpfs zu kopieren :

tmpfs legt alles in den internen Caches des Kernels ab und wächst und schrumpft, um die darin enthaltenen Dateien aufzunehmen

Jorge Nerín
quelle
chattr +Sist nicht dasselbe wie O_DIRECT, es ist dasselbe wie O_SYNC. O_DIRECTbewirkt, dass Lesevorgänge nicht zwischengespeichert werden (worum es in dieser Frage geht), und dass Schreibvorgänge nicht ohne Garantie gepuffert werden. O_SYNCbewirkt, dass nur Schreibvorgänge nicht gepuffert werden.
Gilles 'SO- hör auf böse zu sein'
@ Gilles du hast recht, ich habe die Frage gelesen und darüber nachgedacht, Daten auf die Festplatte zu spülen, wie ich es zuvor getan hatte. Und in diesem Fall gibt es einen weiteren subtilen, aber wichtigen Unterschied zwischen O_DIRECT und O_SYNC. O_DIRECT umgeht den Seitencache, aber O_SYNC erzwingt nicht, dass die Daten (und Metadaten) auf die Festplatte geschrieben werden, sondern durch den Seitencache und wird dort gehalten, um die Lesevorgänge zu beschleunigen. Sollte ich O_DIRECT für O_SYNC in meiner Antwort ändern, um zu verhindern, dass es bei einer falschen Bestätigung bleibt?
Jorge Nerín
Bei dieser Frage geht es darum, eine große Datei so zu halten, dass sie aus dem Cache geschrieben wurde. Ich denke, es mit O_DIRECT zu öffnen, würde sich nachteilig auf die Leistung auswirken, und wenn die große Datei nur angehängt wird, ist der Unterschied möglicherweise gering. Wenn die große Datei jedoch an einer beliebigen Stelle neu geschrieben wird, wird O_DIRECT die Leistung erheblich beeinträchtigen, auch wenn berücksichtigt wird, dass möglicherweise einige der kleinen gelesenen Dateien aus dem Cache entfernt werden.
Jorge Nerín
Wenn Sie O_DIRECTauf O_SYNCändern, wird Ihre Antwort intern konsistent, in Anbetracht der Frage jedoch immer noch falsch.
Gilles 'SO - hör auf, böse zu sein'