
Nachdem ich einige Artikel zum Linux-VFS-Seitencache und den anpassbaren Parametern gelesen hatte, dirty_ratio
hatte ich den Eindruck, dass der Seitencache sowohl als Lese- als auch als Schreib-Caching-Ebene fungieren würde.
Mit dem folgenden einfachen Test lässt sich die Lesegeschwindigkeit für Dateien im Seitencache gut verbessern, beim Schreiben scheint dies jedoch nicht zu funktionieren.
z.B
Cache leeren und in Datei schreiben.
# swapoff -a
# echo 3 > /proc/sys/vm/drop_caches
# dd if=/dev/zero of=/home/flo/test bs=1M count=30
30+0 records in
30+0 records out
31457280 bytes (31 MB) copied, 0.182474 s, 172 MB/s
Überprüfen Sie, ob sich die Datei tatsächlich im Seitencache befindet
# vmtouch /home/flo/test
Files: 1
Directories: 0
Resident Pages: 7680/7680 30M/30M 100%
Elapsed: 0.000673 seconds
Lesen Sie aus der Datei, um zu bestätigen, dass es tatsächlich aus dem Cache kommt.
# dd if=/home/flo/test of=/dev/null bs=1M count=30
30+0 records in
30+0 records out
31457280 bytes (31 MB) copied, 0.00824169 s, 3.8 GB/s
Cache löschen und erneut lesen, um den Geschwindigkeitsunterschied zu beweisen.
# echo 3 > /proc/sys/vm/drop_caches
# dd if=/home/flo/test of=/dev/null bs=1M count=30
30+0 records in
30+0 records out
31457280 bytes (31 MB) copied, 0.132531 s, 237 MB/s
Da ich DIRECT_IO nicht mit dd verwende, habe ich erwartet, dass der Seitencache als Cache vom Typ Writeback verwendet wird. Und basierend darauf dirty_ratio
... dirty_expire_centiseconds
würden die Daten schließlich auf die Festplatte übertragen.
Kann mir bitte jemand erklären, wie VFS den Lese- und Schreibvorgang, insbesondere beim Schreiben, unterschiedlich handhabt und warum dadurch keine Geschwindigkeitssteigerung auftritt.
Gibt es eine Möglichkeit, das VFS beim Schreib-Cache aggressiver zu machen, sodass es sich eher wie der Rückschreib-Cache verhält, den Sie beispielsweise auf einem RAID-Controller finden könnten?
Danke
fLo
Antwort1
man ext4 hat diese Einführung zur (keine) auto_da_alloc
Option:
Viele defekte Anwendungen verwenden fsync() nicht …
Dahinter steckt offenbar eine lange Geschichte (eine Art Tragödie über Datenverlust). Es hat damit zu tunverzögerte Zuteilungvon Dateisystemblöcken. Ext2/3 hatte das nicht, aber es ist ein ziemlich wichtiges Feature, nicht nur von Ext4.
Wenn die Anwendung nicht synchronisiert, der Benutzer nicht manuell und der Kernel erst nach 30 Sekunden, dann sollte das Dateisystem es besser gleich tun, wenn eine Datei neu geschrieben werden muss. Ansonsten können bei DA bei einem Stromausfall leicht schlimme Dinge passieren. Schlimmer als nur die letzten Änderungen zu verlieren.
Ohne conv=notruncate
den dd-Befehl verhält es sich beim Überschreiben wie eine „Anwendung“. Es muss die vorhandene Datei entfernen, um die neue zu erstellen, sonst entsteht ein Mix, wenn die vorhandene Datei länger ist.
Mit mount -o remount,noauto_da_alloc ...
lässt sich dieses Verhalten bei ext4 abschalten. Das Schreiben der Blöcke kann dann erst lange nach dem Abschneiden erfolgen.
Der nächsteGrad der Aggressivitätwäre, die Ablaufzeit von 30 Sekunden und das Prüfintervall von 5 Sekunden (die dirty_..._centisecs-Werte in /proc/sys/vm/) für die periodischen Rückschreibvorgänge zu erhöhen. Mit dem Standardwert 30/5 werden einige neue Dateien einfach eine halbe Minute später geschrieben, es sei denn, Sie sind sehr schnell und löschen schneller.
Je aggressiver das VFS gegenüber ungenutzten Seiten ist, desto weniger aggressiv muss das Dateisystem gegenüber dem Blockgerät sein.
Mount-Optionen und Writeback-Parameter
]# findmnt --real
TARGET SOURCE FSTYPE OPTIONS
/ /dev/sda3 ext4 rw,relatime,noauto_da_alloc
|-/root/sda1 /dev/sda1 ext2 rw,relatime
`-/root/16 /dev/sda16 ext4 rw,relatime
In einem solchen Setup wird ein Überschreiben sofort auf sda16 synchronisiert, aber nicht auf den beiden anderen.
Im Moment habe ich (glaube ich) das regelmäßige Zurückschreiben vollständig ausgeschaltet.
]# grep '' /proc/sys/vm/*centisecs
/proc/sys/vm/dirty_expire_centisecs:720000
/proc/sys/vm/dirty_writeback_centisecs:0
Und jetzt sammle ich endlich schmutzige Seiten:
]# grep nr_dirty /proc/vmstat
nr_dirty 10077
nr_dirty_threshold 437320
nr_dirty_background_threshold 174671
ICHversuchenum sie zu sammeln und irgendwie an das standardmäßige Hintergrundverhältnis von 10 % heranzukommen - ich wurde gestern synchronisiert, als ich in den Suspend-to-Ram-Ruhezustand ging. Macht Sinn: Wer will schon mit MBs schmutziger Seiten schlafen?
mm/writeback.c
ist im Detail sehr komplex, sagen die Kommentare. Ein Problem ist, den Drosselungspunkt nicht zu verpassen, wenn „1000 dd auf einmal schmutzig werden“. „Writeback“ scheint auf lange Sicht auf diese 10 % Bg-Verhältnis abzuzielen. Wie mein obiges Beispiel zeigt, dauert es bei normaler (minimaler) Nutzung lange, bis diese 10 % (des gesamten/verfügbaren RAM) voll sind. Eine Minute Surfen macht ungefähr 1000 Seiten schmutzig.
Nach der Theorie der konkrete Beweis
Ich habe 10 Blöcke auf zwei der oben aufgeführten Dateisysteme getestet:
]# dd if=/dev/zero of=test10 bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB, 10 MiB) copied, 0.0076396 s, 1.4 GB/s
]# dd if=/dev/zero of=test10 bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB, 10 MiB) copied, 0.00514406 s, 2.0 GB/s
-> mit noauto_da_alloc auf der Root-Partition (sda3, oben) ist das Überschreiben noch schneller.
Auf dem standardmäßig gemounteten ext4 (sda16 oben) wird es langsamer:
]# rm test10
]# dd if=/dev/zero of=test10 bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB, 10 MiB) copied, 0.00800839 s, 1.3 GB/s
]# dd if=/dev/zero of=test10 bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB, 10 MiB) copied, 0.0740824 s, 142 MB/s
...weil das gesamte Überschreiben synchronisiert wird, wie vmstat 1 |cut...
gezeigt:
0 0
0 0
0 0
-----io----
bi bo
0 10240
0 0
0 0
Manuell sync
mit verzögerter Zuteilung
Das Gute daran ist: Sie tun es, wann Sie wollen, und Sie können es für einzelne Dateien, aber auch für ganze Laufwerke tun.
Außerdem ist es beim Aushängen, Herunterfahren (und Anhalten) enthalten.
Das Schlimme ist: Das Risiko einer „Korruption“ der Länge Null, wenn zwischen einem (Über-)Schreibvorgang und einer Synchronisierung ein Absturz/Stromausfall auftritt. Das bedeutet, dass Sie wirklich nur das sicher haben, was Sie auf einem oder zwei externen Speichermedien gespeichert haben.
Ich kann kein Fazit finden. Es gibt keine einfache Lösung, nur lange (aber zumindest logische) Erklärungen.
Antwort2
Um das schnelle Verhalten zu sehen, muss ich rm test
zuerst Folgendes tun. Beispielsweise wird dd
1 GB/s statt 150 MB/s gemeldet.
Verweise:
auto_da_alloc
InMann ext4.- LWN.net-Artikel "ext4 und Datenverlust".
- XFS macht in diesem Fall dasselbe, aber nicht im anderen Fall, in dem ext4 dies tut (Umbenennen einer vorhandenen Datei):https://www.spinics.net/lists/xfs/msg36717.html.
Obwohl die Referenzen nur erklären, warum ich daran dachte, dies zu versuchen, erklären sie nicht wirklich, warum es zur Blockierung der E/A führt.
Auf meinem Computer schien die Blockierung nur innerhalb des neuen WBT-Codes ("Writeback Throttling") aufzutreten, der 2016 hinzugefügt wurde.nachSie haben Ihre Frage gestellt. Ich habe nicht analysiertWarumes würde dies verursachen. Und es verschwand, als WBT deaktiviert wurde.
Meine Kernelversion ist 4.18.16-200.fc28.x86_64
.
strace -T
zeigt, dass die ganze Zeit in close() verbracht wurde, was für mich am meisten Sinn macht. Ich habe perf
auch versucht, es zu verwenden. Es funktionierte nicht wie es sollte, aber es zeigte Stacktraces wie
dd 17068 [003] 475165.381526: sched:sched_switch: dd:17068 [120] T ==> kworker/3:1H:19326 [100]
ffffffffa390c172 __sched_text_start+0x352 ([kernel.kallsyms])
ffffffffa390c172 __sched_text_start+0x352 ([kernel.kallsyms])
ffffffffa390c6a8 schedule+0x28 ([kernel.kallsyms])
ffffffffa30def32 io_schedule+0x12 ([kernel.kallsyms])
ffffffffa3461ed7 wbt_wait+0x337 ([kernel.kallsyms])
ffffffffa342ee33 blk_queue_bio+0x123 ([kernel.kallsyms])
ffffffffa342d114 generic_make_request+0x1a4 ([kernel.kallsyms])
ffffffffa342d3c5 submit_bio+0x45 ([kernel.kallsyms])
ffffffffa3377d78 ext4_io_submit+0x48 ([kernel.kallsyms])
ffffffffa335da2c ext4_writepages+0x70c ([kernel.kallsyms])
ffffffffa3209311 do_writepages+0x41 ([kernel.kallsyms])
ffffffffa31f808e __filemap_fdatawrite_range+0xbe ([kernel.kallsyms])
ffffffffa334b9ec ext4_release_file+0x6c ([kernel.kallsyms])
ffffffffa32a9d4e __fput+0xae ([kernel.kallsyms])
ffffffffa30cf474 task_work_run+0x84 ([kernel.kallsyms])
ffffffffa3003e6e exit_to_usermode_loop+0xce ([kernel.kallsyms])
ffffffffa300425d do_syscall_64+0x14d ([kernel.kallsyms])
ffffffffa3a00088 entry_SYSCALL_64_after_hwframe+0x44 ([kernel.kallsyms])
7fcca3a60654 __close+0x14 (/usr/lib64/libc-2.27.so)
was mich daran erinnerte, dass ich gerade den I/O-Scheduler testete deadline
, wobei WBT („Writeback Throttling“) aktiviert war. Durch Deaktivieren von WBT (auch durch Umschalten auf CFQ, das inkompatibel ist) wurde das schnelle Verhalten wiederhergestellt!
Die perf
Befehle, die ich verwendet habe, um dies zu sehen, waren:
sudo perf record -e sched:sched_stat_sleep -e sched:sched_switch -e sched:sched_process_exit -gP -o ~/perf.data dd if=/dev/zero of=test bs=1M count=30
sudo perf script -i ~/perf.data | cat
Antwort3
Verwenden Sie einfach nicht dd
. Verwenden Sie beispielsweise , cp
und Sie erhalten problemlos einen Seitencache für Schreibvorgänge.