30% des Arbeitsspeichers sind "Puffer". Was ist es?

12
$ free -h
              total        used        free      shared  buff/cache   available
Mem:           501M        146M         19M        9.7M        335M        331M
Swap:          1.0G         85M        938M

$ free -w -h
              total        used        free      shared     buffers       cache   available
Mem:           501M        146M         19M        9.7M        155M        180M        331M
Swap:          1.0G         85M        938M

Wie kann ich "Puffer" in der Ausgabe von beschreiben oder erklären free?

Ich habe kein (bekanntes) Problem mit diesem System. Ich bin nur überrascht und neugierig zu sehen, dass "Puffer" fast so hoch sind wie "Cache" (155M vs 180M). Ich dachte, "Cache" repräsentiert den Seiten-Cache des Dateiinhalts und ist in der Regel der wichtigste Teil von "Cache / Puffer". Mir ist weniger klar, wofür "Puffer" sind.

Zum Beispiel habe ich dies mit meinem Laptop verglichen, der mehr RAM hat. Auf meinem Laptop ist die Zahl "Puffer" um eine Größenordnung kleiner als "Cache" (200M vs 4G). Wenn ich genau verstehen würde, was "Puffer" sind, könnte ich mich fragen, warum die Puffer auf dem kleineren System zu einem so größeren Anteil wachsen könnten.

man proc (Ich ignoriere die unglaublich veraltete Definition von "groß"):

Puffer% lu

Relativ temporärer Speicher für unformatierte Festplattenblöcke, die nicht sehr groß werden sollten (ca. 20 MB).

Zwischengespeichert% lu

In-Memory-Cache für Dateien, die von der Festplatte gelesen werden (der Seiten-Cache). Enthält SwapCached nicht.


$ free -V
free from procps-ng 3.3.12
$ uname -r
4.9.0-6-marvell
$ systemd-detect-virt
none

$ cat /proc/meminfo
MemTotal:         513976 kB
MemFree:           20100 kB
MemAvailable:     339304 kB
Buffers:          159220 kB
Cached:           155536 kB
SwapCached:         2420 kB
Active:           215044 kB
Inactive:         216760 kB
Active(anon):      56556 kB
Inactive(anon):    73280 kB
Active(file):     158488 kB
Inactive(file):   143480 kB
Unevictable:       10760 kB
Mlocked:           10760 kB
HighTotal:             0 kB
HighFree:              0 kB
LowTotal:         513976 kB
LowFree:           20100 kB
SwapTotal:       1048572 kB
SwapFree:         960532 kB
Dirty:               240 kB
Writeback:             0 kB
AnonPages:        126912 kB
Mapped:            40312 kB
Shmem:              9916 kB
Slab:              37580 kB
SReclaimable:      29036 kB
SUnreclaim:         8544 kB
KernelStack:        1472 kB
PageTables:         3108 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     1305560 kB
Committed_AS:    1155244 kB
VmallocTotal:     507904 kB
VmallocUsed:           0 kB
VmallocChunk:          0 kB

$ sudo slabtop --once
 Active / Total Objects (% used)    : 186139 / 212611 (87.5%)
 Active / Total Slabs (% used)      : 9115 / 9115 (100.0%)
 Active / Total Caches (% used)     : 66 / 92 (71.7%)
 Active / Total Size (% used)       : 31838.34K / 35031.49K (90.9%)
 Minimum / Average / Maximum Object : 0.02K / 0.16K / 4096.00K

  OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME                   
 59968  57222   0%    0.06K    937       64      3748K buffer_head            
 29010  21923   0%    0.13K    967       30      3868K dentry                 
 24306  23842   0%    0.58K   4051        6     16204K ext4_inode_cache       
 22072  20576   0%    0.03K    178      124       712K kmalloc-32             
 10290   9756   0%    0.09K    245       42       980K kmalloc-96             
  9152   4582   0%    0.06K    143       64       572K kmalloc-node           
  9027   8914   0%    0.08K    177       51       708K kernfs_node_cache      
  7007   3830   0%    0.30K    539       13      2156K radix_tree_node        
  5952   4466   0%    0.03K     48      124       192K jbd2_revoke_record_s   
  5889   5870   0%    0.30K    453       13      1812K inode_cache            
  5705   4479   0%    0.02K     35      163       140K file_lock_ctx          
  3844   3464   0%    0.03K     31      124       124K anon_vma               
  3280   3032   0%    0.25K    205       16       820K kmalloc-256            
  2730   2720   0%    0.10K     70       39       280K btrfs_trans_handle     
  2025   1749   0%    0.16K     81       25       324K filp                   
  1952   1844   0%    0.12K     61       32       244K kmalloc-128            
  1826    532   0%    0.05K     22       83        88K trace_event_file       
  1392   1384   0%    0.33K    116       12       464K proc_inode_cache       
  1067   1050   0%    0.34K     97       11       388K shmem_inode_cache      
   987    768   0%    0.19K     47       21       188K kmalloc-192            
   848    757   0%    0.50K    106        8       424K kmalloc-512            
   450    448   0%    0.38K     45       10       180K ubifs_inode_slab       
   297    200   0%    0.04K      3       99        12K eventpoll_pwq          
   288    288 100%    1.00K     72        4       288K kmalloc-1024           
   288    288 100%    0.22K     16       18        64K mnt_cache              
   287    283   0%    1.05K     41        7       328K idr_layer_cache        
   240      8   0%    0.02K      1      240         4K fscrypt_info           
sourcejedi
quelle
3
linuxatemyram.com ist nützlich zu lesen
Basile Starynkevitch

Antworten:

12
  1. Was ist der Unterschied zwischen "Puffer" und dem anderen Cache?
  2. Warum sehen wir diese Unterscheidung so prominent? (Möglicher historischer Grund)
  3. Wofür werden Buffersverwendet?
  4. Warum können wir Buffersinsbesondere erwarten , dass sie größer oder kleiner sind?

1. Was ist der Unterschied zwischen "Puffer" und dem anderen Cache-Typ?

BuffersGibt die Größe des Seitencaches an, der für Blockgeräte verwendet wird. Der Kernel muss diesen Betrag absichtlich vom Rest des Seitencaches abziehen, wenn er meldet Cached.

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 sehen wir diese Unterscheidung so deutlich? (Möglicher historischer Grund)

Der Seitencache arbeitet in Einheiten der MMU-Seitengröße, normalerweise mindestens 4096 Byte. Dies ist wichtig für den mmap()Zugriff auf speicherabgebildete Dateien. [1] [2] Es wird verwendet, um Seiten mit geladenem Programm- / Bibliothekscode für unabhängige Prozesse freizugeben und das Laden einzelner Seiten bei Bedarf zu ermöglichen. (Auch zum Entladen von Seiten, wenn etwas anderes den Speicherplatz benötigt und diese in letzter Zeit nicht verwendet wurden).

[1] Speicherzugeordnete E / A - Das Handbuch zur GNU C-Bibliothek.
[2] mmap- Wikipedia.

Frühe UNIX hatte einen "Puffer-Cache" von Plattenblöcken und hatte keine mmap (). Anscheinend haben sie beim erstmaligen Hinzufügen von mmap () einfach den Seiten-Cache über den Puffer-Cache geschraubt. Das ist so chaotisch, wie es sich anhört. Schließlich haben UNIX-basierte Betriebssysteme den Puffercache entfernt. Der gesamte Datei-Cache befindet sich jetzt in Seiteneinheiten. Seiten werden nach (Datei, Versatz) und nicht nach Speicherort auf der Festplatte gesucht. Dies wurde als "einheitlicher Puffercache" bezeichnet, möglicherweise weil die Leute mit "Puffercache" besser vertraut waren. [3]

[3] UBC: Ein effizientes einheitliches E / A- und Speicher-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, mit der Seite in Form einer Liste von buffer_headStrukturen zwischengespeichert werden. Wenn eine geänderte Seite auf die Festplatte zurückgeschrieben werden soll, wird die E / A. Anforderungen können sofort an den Gerätetreiber gesendet werden, ohne dass indirekte Blöcke gelesen werden müssen, um zu bestimmen, wo 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, jedoch nicht für Lesevorgänge. "Der Seitencache hat den Puffercache verwendet, um seine Daten zurückzuschreiben, eine zusätzliche Kopie der Daten zu benötigen und den Speicherbedarf für einige Schreiblasten zu verdoppeln" (?). [4] Machen wir uns nicht zu viele Gedanken über die Details, aber diese Historie wäre ein Grund, warum Linux die BuffersNutzung separat meldet .

[4] Seitenersetzung in der Linux 2.4-Speicherverwaltung , Rik van Riel.

Im Gegensatz dazu ist in Linux 2.4 und höher die zusätzliche Kopie nicht vorhanden. "Das System führt Festplatten-E / A direkt zur und von der Seiten-Cache-Seite aus." [4] Linux 2.4 wurde 2001 veröffentlicht.

3. Wofür werden Buffersverwendet?

Blockgeräte werden als Dateien behandelt und verfügen daher über einen Seitencache. Dies wird "für Dateisystem-Metadaten und das Caching von Raw-Block-Geräten" verwendet. [4] In aktuellen Linux-Versionen kopieren Dateisysteme jedoch keinen Dateiinhalt, sodass kein "doppeltes Caching" erfolgt.

Ich stelle mir den BuffersTeil des Seitencaches als Linux-Puffercache vor. Obwohl einige Quellen mit dieser Terminologie nicht einverstanden sind.

Wie viel Puffer-Cache das Dateisystem verwendet, hängt von den Details des jeweiligen Dateisystems ab. Das fragliche System verwendet ext4. ext3 / ext4 verwendet den Linux-Puffercache für das Journal, für Verzeichnisinhalte und einige andere Metadaten.

Bestimmte Dateisysteme, einschließlich ext3, ext4 und ocfs2, verwenden die Ebene jbd oder jbd2, um ihre physische Blockaufzeichnung zu verarbeiten, und diese Ebene verwendet grundsätzlich den Puffercache.

- E-Mail-Artikel von Ted Tso , 2013

Vor der Linux-Kernel-Version 2.4 verfügte Linux über separate Seiten- und Puffer-Caches. Seit 2.4 sind der Seiten- und der Puffercache vereinheitlicht und es Buffershandelt sich um unformatierte Plattenblöcke, die nicht im Seitencache dargestellt sind, dh keine Dateidaten.

...

Der Puffercache bleibt jedoch bestehen, da der Kernel weiterhin Block-E / A 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 Puffercaches durch den Seitencache dargestellt. Eine kleine Menge von Blockdaten ist jedoch nicht dateibasiert - beispielsweise Metadaten und Rohblock-E / A - und wird daher ausschließlich durch den Puffercache dargestellt.

- 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 befasst sich genauer mit technischen Details. Die zweite Quelle ist eine allgemeinere Zusammenfassung, die in einigen Einzelheiten widersprochen und veraltet sein könnte.

Es ist richtig, dass Dateisysteme möglicherweise Metadaten zum Schreiben von Teilseiten ausführen, obwohl der Cache in Seiten indiziert ist. Sogar Benutzerprozesse können Teil-Seiten-Schreibvorgänge ausführen, wenn sie write()(im Gegensatz zu mmap()) zumindest direkt auf einem Blockgerät verwenden. Dies gilt nur für Schreibvorgänge, nicht für Lesevorgänge. Wenn Sie den Seitencache lesen, liest der Seitencache immer ganze Seiten.

Linus mochte es zu schimpfen, dass der Puffercache nicht erforderlich ist, um Schreibvorgänge in Blockgröße auszuführen, und dass Dateisysteme Metadatenschreibvorgänge für Teilseiten ausführen können, selbst wenn der Seitencache an ihre eigenen Dateien anstelle des Blockgeräts angehängt ist. Ich bin sicher, er hat Recht zu sagen, dass ext2 dies tut. ext3 / ext4 mit seinem Journalling-System nicht. Es ist weniger klar, welche Probleme zu diesem Entwurf geführt haben. Die Leute, die er beschimpfte, hatten es satt zu erklären.

ext4_readdir () wurde nicht geändert, um Linus 'Rant zu erfüllen. 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 Seitencache überhaupt nicht für readdir (). Es verwendet einen eigenen Cache für Bäume. Ich könnte etwas in btrfs vermissen.

4. Warum können wir Buffersinsbesondere erwarten , dass sie größer oder kleiner sind?

In diesem Fall stellt sich heraus, dass die ext4-Journalgröße für mein Dateisystem 128 MB beträgt. Dies erklärt, warum 1) sich mein Puffercache bei etwas mehr als 128 MB stabilisieren kann; 2) Der Puffer-Cache skaliert nicht proportional zur größeren RAM-Größe meines Laptops.

Weitere mögliche Ursachen finden Sie unter Was ist die Spalte Puffer in der Ausgabe von free? Beachten Sie, dass "Puffer", die von gemeldet werden, freetatsächlich eine Kombination aus Buffersund wiedergewinnbarem Plattenspeicher sind.


Um zu überprüfen, ob Journalschreibvorgänge den Puffercache verwenden, habe ich ein Dateisystem in einem schönen 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 Ted Tsos E-Mail gefunden und war fasziniert, dass es das Schreiben- Caching betonte . Ich würde es überraschend finden, wenn "schmutzige", ungeschriebene Daten 30% des Arbeitsspeichers auf meinem System erreichen könnten. sudo atopzeigt, dass das betreffende System über einen Zeitraum von 10 Sekunden konsistent nur 1 MB schreibt. Das betreffende Dateisystem könnte mit der über 100-fachen Rate mithalten. (Es befindet sich auf einem USB2-Festplattenlaufwerk, maximaler Durchsatz ~ 20 MB / s).

Die Verwendung von blktrace ( btrace -w 10 /dev/sda) bestätigt, dass die zwischengespeicherten E / A-Vorgänge Schreibvorgänge sein müssen, da fast keine Daten gelesen werden. Dies mysqldist auch der einzige Userspace- Prozess, der E / A ausführt.

Ich habe den für das Schreiben verantwortlichen Dienst (icinga2-Schreiben in MySQL) gestoppt und erneut überprüft. Ich habe gesehen, wie "Puffer" auf unter 20 Millionen gefallen sind - ich habe keine Erklärung dafür - und bin dort geblieben. Beim erneuten Starten des Writers werden "Puffer" angezeigt, die für jedes 10-Sekunden-Intervall um ~ 0,1 M ansteigen. Ich habe beobachtet, dass diese Rate konstant gehalten wird und auf 70 Millionen und mehr zurückgegangen ist.

Das Laufen echo 3 | sudo tee /proc/sys/vm/drop_cacheswar ausreichend, um die "Puffer" wieder auf 4,5 M zu senken. Dies beweist, dass meine Ansammlung von Puffern ein "sauberer" Cache ist, den Linux bei Bedarf sofort löschen kann. Dieses System sammelt keine ungeschriebenen Daten. ( drop_cachesführt kein Zurückschreiben durch und kann daher keine schmutzigen Seiten löschen. Wenn Sie einen Test ausführen möchten, der zuerst den Cache bereinigt, verwenden Sie den syncBefehl).

Das gesamte MySQL-Verzeichnis ist nur 150M groß. Die akkumulierten Puffer müssen Metadatenblöcke aus MySQL-Schreibvorgängen darstellen, aber es hat mich überrascht zu glauben, dass es für diese Daten so viele Metadatenblöcke geben würde.

sourcejedi
quelle
3

Ihre Version von freehat die richtige Idee. Standardmäßig werden Puffer und Cache in seinem Bericht kombiniert. Dies liegt daran, dass sie im Grunde dasselbe sind. Sie sind beide der Computer, der sich im RAM (schneller als der 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 besser von etwas anderem genutzt wird, kann es ihn freigeben. Sorgen Sie sich daher nicht um Puffer und Cache.

Das Ansehen einer DVD kann jedoch dazu führen, dass der Puffer hoch wird und andere Puffer- / Cache-Inhalte entfernt werden. Daher können Sie Nocache verwenden, um den DVD-Player auszuführen ( wenn dies ein Problem verursacht ).

Strg-Alt-Delor
quelle