- Was ist der Unterschied zwischen "Puffer" und anderen Cache-Typen?
- Warum ist diese Unterscheidung so stark ausgeprägt? Warum sagen manche Leute "Puffer-Cache", wenn sie über zwischengespeicherte Dateiinhalte sprechen?
- Was sind
Buffers
verwendet für? - Warum sollten wir
Buffers
erwarten insbesondere größer oder kleiner?
1. Was ist der Unterschied zwischen "Puffer" und anderen Cache-Typen?
Buffers
zeigt die Menge an Seitencache, die für Blockgeräte verwendet wird. "Blockgeräte" sind die gängigste Art von Datenspeichergeräten.
Der Kernel muss diesen Betrag absichtlich vom Rest des Seiten-Cache abziehen, wenn er Cached
meldet . Siehe meminfo_proc_show():
cached = global_node_page_state(NR_FILE_PAGES) -
total_swapcache_pages() - i.bufferram;
...
show_val_kb(m, "MemTotal: ", i.totalram);
show_val_kb(m, "MemFree: ", i.freeram);
show_val_kb(m, "MemAvailable: ", available);
show_val_kb(m, "Buffers: ", i.bufferram);
show_val_kb(m, "Cached: ", cached);
2. Warum wird diese Unterscheidung so deutlich gemacht? Warum sagen manche Leute "Puffer-Cache", wenn sie über zwischengespeicherte Dateiinhalte sprechen?
Der Seitencache arbeitet in Einheiten der MMU-Seitengröße, normalerweise mindestens 4096 Bytes. Dies ist für mmap()
unerlässlich , d.h. speicherabgebildeter Dateizugriff.[1][2] Es wurde entwickelt, um Seiten mit geladenem Programm-/Bibliothekscode zwischen separaten Prozessen zu teilen und das Laden einzelner Seiten bei Bedarf zu ermöglichen. (Auch zum Entladen von Seiten, wenn etwas anderes den Platz benötigt und sie in letzter Zeit nicht verwendet wurden).
[1] Memory-mapped I/O - Das Handbuch der GNU C-Bibliothek.
[2] mmap
-Wikipedia.
Das frühe UNIX hatte einen "Puffer-Cache" von Plattenblöcken und kein mmap(). Als mmap() zum ersten Mal hinzugefügt wurde, fügten sie anscheinend den Seiten-Cache als neue Ebene oben hinzu. Das ist so chaotisch, wie es sich anhört. Schließlich haben UNIX-basierte Betriebssysteme den separaten Puffer-Cache abgeschafft. Jetzt ist also der gesamte Datei-Cache in Einheiten von Seiten. Seiten werden nach (Datei, Offset) gesucht, nicht nach Speicherort auf der Festplatte. Dies wurde "Unified Buffer Cache" genannt, vielleicht weil die Leute mit "Buffer Cache" besser vertraut waren.[3]
[3] UBC:Ein effizientes Unified-I/O- und Memory-Caching-Subsystem für NetBSD
("Eine interessante Wendung, die Linux hinzufügt, ist, dass die Geräteblocknummern, in denen eine Seite auf der Festplatte gespeichert ist, zusammen mit der Seite in Form einer Liste von buffer_head
zwischengespeichert werden Strukturen. Wenn eine modifizierte Seite auf die Festplatte zurückgeschrieben werden soll, können die E/A-Anforderungen sofort an den Gerätetreiber gesendet werden, ohne dass irgendwelche indirekten Blöcke gelesen werden müssen, um zu bestimmen, wohin die Daten der Seite geschrieben werden sollen."[3])
In Linux 2.2 gab es einen separaten "Puffer-Cache", der für Schreibvorgänge verwendet wurde, aber nicht für Lesevorgänge. "Der Seiten-Cache verwendete den Puffer-Cache, um seine Daten zurückzuschreiben, benötigte eine zusätzliche Kopie der Daten und verdoppelte den Speicherbedarf für einige Schreiblasten."[4] Machen wir uns nicht zu viele Gedanken über die Details, aber dieser Verlauf wäre einer der Gründe, warum Linux Buffers
meldet Verwendung separat.
[4] Seitenersetzung in der Speicherverwaltung von Linux 2.4, Rik van Riel.
Im Gegensatz dazu existiert in Linux 2.4 und höher die zusätzliche Kopie nicht. "Das System führt Platten-IO direkt zu und von der Seiten-Cache-Seite aus."[4] Linux 2.4 wurde 2001 veröffentlicht.
3. Was sind Buffers
verwendet für?
Blockgeräte werden als Dateien behandelt und haben daher einen Seitencache. Dies wird "für Dateisystem-Metadaten und das Caching von Raw-Block-Geräten" verwendet.[4] Aber in aktuellen Linux-Versionen kopieren Dateisysteme Dateiinhalte nicht durch, daher gibt es kein "doppeltes Caching".
Ich denke an den Buffers
Teil des Seiten-Cache als Linux-Puffer-Cache. Einige Quellen könnten mit dieser Terminologie nicht einverstanden sein.
Wie viel Puffer-Cache das Dateisystem verwendet, wenn überhaupt, hängt von der Art des Dateisystems ab. Das fragliche System verwendet ext4. ext3/ext4 verwenden den Linux-Puffer-Cache für das Journal, für Verzeichnisinhalte und einige andere Metadaten.
Bestimmte Dateisysteme, einschließlich ext3, ext4 und ocfs2, verwenden die jbd- oder jbd2-Schicht, um ihr physisches Block-Journaling zu handhaben, und diese Schicht verwendet grundsätzlich den Puffer-Cache.
-- E-Mail-Artikel von Ted Tso, 2013
Vor der Linux-Kernel-Version 2.4 hatte Linux separate Seiten- und Puffer-Caches. Seit 2.4 sind Seiten- und Puffercache vereinheitlicht und Buffers
sind unformatierte Festplattenblöcke, die nicht im Seitencache dargestellt werden – d. h. keine Dateidaten.
...
Der Puffer-Cache bleibt jedoch erhalten, da der Kernel weiterhin Block-I/O in Form von Blöcken und nicht von Seiten ausführen muss. Da die meisten Blöcke Dateidaten darstellen, wird der größte Teil des Puffer-Cache durch den Seiten-Cache dargestellt. Aber eine kleine Menge Blockdaten ist nicht dateigesichert – beispielsweise Metadaten und rohe Block-I/O – und wird daher ausschließlich durch den Puffercache repräsentiert.
-- Ein Paar Quora-Antworten von Robert Love, zuletzt aktualisiert 2013.
Beide Autoren sind Linux-Entwickler, die mit der Speicherverwaltung des Linux-Kernels gearbeitet haben. Die erste Quelle ist spezifischer in Bezug auf technische Details. Die zweite Quelle ist eine allgemeinere Zusammenfassung, die in einigen Einzelheiten widersprüchlich und veraltet sein könnte.
Es ist wahr, dass Dateisysteme Teilseiten-Metadatenschreibvorgänge ausführen können, obwohl der Cache in Seiten indiziert ist. Sogar Benutzerprozesse können partielle Seitenschreibvorgänge ausführen, wenn sie write()
verwenden (im Gegensatz zu mmap()
), zumindest direkt an ein Blockgerät. Dies gilt nur für Schreibvorgänge, nicht für Lesevorgänge. Wenn Sie den Seiten-Cache durchlesen, liest der Seiten-Cache immer ganze Seiten.
Linus schimpfte gerne darüber, dass der Buffer-Cache nicht benötigt wird, um Schreibvorgänge in Blockgröße durchzuführen, und dass Dateisysteme Teilseiten-Metadaten schreiben können, selbst wenn der Seiten-Cache an ihre eigenen Dateien anstelle des Blockgeräts angehängt ist. Ich bin sicher, dass er Recht hat, wenn er sagt, dass ext2 dies tut. ext3/ext4 mit seinem Journalsystem nicht. Weniger klar ist, welche Probleme zu diesem Design geführt haben. Die Leute, auf die er schimpfte, waren es leid, es zu erklären.
ext4_readdir() wurde nicht geändert, um Linus' Tirade zu befriedigen. Ich sehe seinen gewünschten Ansatz auch nicht in readdir () anderer Dateisysteme. Ich denke, XFS verwendet den Puffercache auch für Verzeichnisse. bcachefs verwendet den Seiten-Cache für readdir() überhaupt nicht; es verwendet seinen eigenen Cache für Btrees. Bei btrfs bin ich mir nicht sicher.
4. Warum sollten wir Buffers
erwarten insbesondere größer oder kleiner?
In diesem Fall stellt sich heraus, dass die ext4-Journalgröße für mein Dateisystem 128 MB beträgt. Das erklärt also, warum 1) sich mein Puffer-Cache bei etwas über 128 MB stabilisieren kann; 2) Puffer-Cache skaliert nicht proportional mit der größeren RAM-Menge auf meinem Laptop.
Weitere mögliche Ursachen finden Sie unter Was ist die Pufferspalte in der Ausgabe von free? Beachten Sie, dass "Puffer" von free
gemeldet werden ist eigentlich eine Kombination aus Buffers
und zurückgewinnbarer Kernel-Slab-Speicher.
Um zu überprüfen, ob Journal-Schreibvorgänge den Puffer-Cache verwenden, habe ich ein Dateisystem in schönem schnellen RAM (tmpfs) simuliert und die maximale Puffernutzung für verschiedene Journalgrößen verglichen.
# dd if=/dev/zero of=/tmp/t bs=1M count=1000
...
# mkfs.ext4 /tmp/t -J size=256
...
# LANG=C dumpe2fs /tmp/t | grep '^Journal size'
dumpe2fs 1.43.5 (04-Aug-2017)
Journal size: 256M
# mount /tmp/t /mnt
# cd /mnt
# free -w -m
total used free shared buffers cache available
Mem: 7855 2521 4321 285 66 947 5105
Swap: 7995 0 7995
# for i in $(seq 40000); do dd if=/dev/zero of=t bs=1k count=1 conv=sync status=none; sync t; sync -f t; done
# free -w -m
total used free shared buffers cache available
Mem: 7855 2523 3872 551 237 1223 4835
Swap: 7995 0 7995
# dd if=/dev/zero of=/tmp/t bs=1M count=1000
...
# mkfs.ext4 /tmp/t -J size=16
...
# LANG=C dumpe2fs /tmp/t | grep '^Journal size'
dumpe2fs 1.43.5 (04-Aug-2017)
Journal size: 16M
# mount /tmp/t /mnt
# cd /mnt
# free -w -m
total used free shared buffers cache available
Mem: 7855 2507 4337 285 66 943 5118
Swap: 7995 0 7995
# for i in $(seq 40000); do dd if=/dev/zero of=t bs=1k count=1 conv=sync status=none; sync t; sync -f t; done
# free -w -m
total used free shared buffers cache available
Mem: 7855 2509 4290 315 77 977 5086
Swap: 7995 0 7995
Geschichte dieser Antwort:Wie ich dazu kam, mir das Tagebuch anzusehen
Ich hatte zuerst die E-Mail von Ted Tso gefunden und war fasziniert, dass darin Schreiben betont wurde zwischenspeichern. Ich fände es überraschend, wenn "schmutzig", ungeschrieben Daten konnten 30% des RAM auf meinem System erreichen. sudo atop
zeigt, dass das betreffende System über ein 10-Sekunden-Intervall konstant nur 1 MB schreibt. Das betreffende Dateisystem würde mit einer über 100-fachen Rate mithalten können. (Es befindet sich auf einem USB2-Festplattenlaufwerk, maximaler Durchsatz ~20 MB/s).
Mit blktrace (btrace -w 10 /dev/sda
) bestätigt, dass die zwischengespeicherten IOs geschrieben werden müssen, da fast keine Daten gelesen werden. Auch das mysqld
ist der einzige userspace Prozess, der IO ausführt.
Ich habe den Dienst gestoppt, der für die Schreibvorgänge verantwortlich ist (icinga2 schreibt nach mysql) und es erneut überprüft. Ich habe gesehen, wie "Puffer" auf unter 20 Millionen abfielen - ich habe keine Erklärung dafür - und dort blieben. Ein erneuter Neustart des Writers zeigt, dass "Puffer" für jedes 10-Sekunden-Intervall um ~ 0,1 Mio. ansteigen. Ich habe beobachtet, dass es diese Rate konstant beibehält und auf 70 Millionen und mehr zurückklettert.
Ausführen von echo 3 | sudo tee /proc/sys/vm/drop_caches
reichte aus, um die "Puffer" wieder auf 4,5 MB zu senken. Dies beweist, dass meine Ansammlung von Puffern ein "sauberer" Cache ist, den Linux bei Bedarf sofort löschen kann. Dieses System akkumuliert nicht ungeschrieben Daten. (drop_caches
führt kein Rückschreiben durch und kann daher keine schmutzigen Seiten löschen. Wenn Sie einen Test ausführen möchten, der zuerst den Cache bereinigt, würden Sie den sync
verwenden Befehl).
Das gesamte MySQL-Verzeichnis ist nur 150 MB groß. Die sich ansammelnden Puffer müssen Metadatenblöcke aus mysql-Schreibvorgängen darstellen, aber es überraschte mich zu glauben, dass es so viele Metadatenblöcke für diese Daten geben würde.
Ihre Version von free
hat die richtige Idee. Standardmäßig kombiniert es Puffer und Cache in seinem Bericht. Dies liegt daran, dass sie im Grunde dasselbe sind. Sie sind beide der Computer, der sich im RAM (schneller als Sekundärspeicher:Festplatten und SSD) erinnert, was er bereits beim Lesen von Festplatte und SSD gesehen hat.
Wenn das Betriebssystem der Meinung ist, dass der Speicher von etwas anderem besser verwendet wird, kann es ihn freigeben. Machen Sie sich daher keine Gedanken über Puffer und Cache.
Das Ansehen einer DVD kann jedoch dazu führen, dass der Puffer ansteigt und andere Puffer-/Cache-Inhalte gelöscht werden. Daher können Sie nocache verwenden, um den DVD-Player auszuführen (wenn es ein Problem verursacht ).