Verbessert die Option „bs“ in „dd“ wirklich die Geschwindigkeit?

58

Hin und wieder wird mir gesagt, dass ich zur Erhöhung der Geschwindigkeit eines "dd" sorgfältig eine richtige "Blockgröße" auswählen sollte.

Selbst hier, auf ServerFault, schrieb jemand anderes , dass " ... die optimale Blockgröße hardwareabhängig ist ... " (iain) oder " ... die perfekte Größe von Ihrem Systembus, dem Festplattencontroller und dem jeweiligen Laufwerk abhängt selbst und die Treiber für jeden von denen ... " (chris-s)

Da mein Gefühl ein bisschen anders war ( Übrigens: Ich habe gemerkt, dass die Zeit, die benötigt wird, um den bs-Parameter gründlich abzustimmen, in Bezug auf die Zeitersparnis viel höher war als die erhaltene Verstärkung, und dass die Standardeinstellung vernünftig war ), bin ich heute einfach gegangen durch einige schnelle und schmutzige Benchmarks.

Um äußere Einflüsse zu verringern, entschied ich mich zu lesen:

  • von einer externen MMC-Karte
  • von einer internen Partition

und:

  • mit verwandten Dateisystemen umountet
  • Senden der Ausgabe an / dev / null, um Probleme im Zusammenhang mit der "Schreibgeschwindigkeit" zu vermeiden;
  • Vermeiden einiger grundlegender Probleme beim Zwischenspeichern von Festplatten, zumindest wenn die Festplatte betroffen ist.

In der folgenden Tabelle habe ich meine Ergebnisse angegeben, indem ich 1 GB Daten mit unterschiedlichen Werten von "bs" gelesen habe ( die unformatierten Zahlen finden Sie am Ende dieser Nachricht ):

Bildbeschreibung hier eingeben

Grundsätzlich stellt sich heraus, dass:

  • MMC: Mit einem bs = 4 (ja! 4 Bytes) habe ich einen Durchsatz von 12MB / s erreicht. Ein nicht so entfernter Wert für das Maximum von 14.2 / 14.3, den ich von bs = 5 und höher erhalten habe;

  • HDD: mit einem bs = 10 habe ich 30 MB / s erreicht. Sicher niedriger als die 95,3 MB, mit der Standardeinstellung bs = 512, aber ... auch signifikant.

Es war auch sehr klar, dass die Systemzeit der CPU umgekehrt proportional zum Wert von bs war (dies klingt jedoch vernünftig, da die Anzahl der von dd generierten Systemaufrufe umso höher ist, je niedriger der Wert von bs ist).

Nach alledem stellt sich nun die Frage: Kann jemand erklären (einen Kernel-Hacker?), Welche Hauptkomponenten / -systeme an einem solchen Durchsatz beteiligt sind und ob es sich wirklich lohnt, ein höheres BS als das Standard-BS anzugeben?


MMC-Fall - rohe Zahlen

bs = 1 M

root@iMac-Chiara:/tmp# time dd if=/dev/sdc of=/dev/null bs=1M count=1000
1000+0 record dentro
1000+0 record fuori
1048576000 byte (1,0 GB) copiati, 74,1239 s, 14,1 MB/s

real    1m14.126s
user    0m0.008s
sys     0m1.588s

bs = 1k

root@iMac-Chiara:/tmp# time dd if=/dev/sdc of=/dev/null bs=1k count=1000000
1000000+0 record dentro
1000000+0 record fuori
1024000000 byte (1,0 GB) copiati, 72,7795 s, 14,1 MB/s

real    1m12.782s
user    0m0.244s
sys     0m2.092s

bs = 512

root@iMac-Chiara:/tmp# time dd if=/dev/sdc of=/dev/null bs=512 count=2000000
2000000+0 record dentro
2000000+0 record fuori
1024000000 byte (1,0 GB) copiati, 72,867 s, 14,1 MB/s

real    1m12.869s
user    0m0.324s
sys     0m2.620s

bs = 10

root@iMac-Chiara:/tmp# time dd if=/dev/sdc of=/dev/null bs=10 count=100000000
100000000+0 record dentro
100000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 70,1662 s, 14,3 MB/s

real    1m10.169s
user    0m6.272s
sys     0m28.712s

bs = 5

root@iMac-Chiara:/tmp# time dd if=/dev/sdc of=/dev/null bs=5 count=200000000
200000000+0 record dentro
200000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 70,415 s, 14,2 MB/s

real    1m10.417s
user    0m11.604s
sys     0m55.984s

bs = 4

root@iMac-Chiara:/tmp# time dd if=/dev/sdc of=/dev/null bs=4 count=250000000
250000000+0 record dentro
250000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 80,9114 s, 12,4 MB/s

real    1m20.914s
user    0m14.436s
sys     1m6.236s

bs = 2

root@iMac-Chiara:/tmp# time dd if=/dev/sdc of=/dev/null bs=2 count=500000000
500000000+0 record dentro
500000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 161,974 s, 6,2 MB/s

real    2m41.976s
user    0m28.220s
sys     2m13.292s

bs = 1

root@iMac-Chiara:/tmp# time dd if=/dev/sdc of=/dev/null bs=1 count=1000000000
1000000000+0 record dentro
1000000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 325,316 s, 3,1 MB/s

real    5m25.318s
user    0m56.212s
sys     4m28.176s

Festplattengehäuse - rohe Zahlen

bs = 1

root@iMac-Chiara:/tmp# time dd if=/dev/sda3 of=/dev/null bs=1 count=1000000000
1000000000+0 record dentro
1000000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 341,461 s, 2,9 MB/s

real    5m41.463s
user    0m56.000s
sys 4m44.340s

bs = 2

root@iMac-Chiara:/tmp# time dd if=/dev/sda3 of=/dev/null bs=2 count=500000000
500000000+0 record dentro
500000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 164,072 s, 6,1 MB/s

real    2m44.074s
user    0m28.584s
sys 2m14.628s

bs = 4

root@iMac-Chiara:/tmp# time dd if=/dev/sda3 of=/dev/null bs=4 count=250000000
250000000+0 record dentro
250000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 81,471 s, 12,3 MB/s

real    1m21.473s
user    0m14.824s
sys 1m6.416s

bs = 5

root@iMac-Chiara:/tmp# time dd if=/dev/sda3 of=/dev/null bs=5 count=200000000
200000000+0 record dentro
200000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 66,0327 s, 15,1 MB/s

real    1m6.035s
user    0m11.176s
sys 0m54.668s

bs = 10

root@iMac-Chiara:/tmp# time dd if=/dev/sda3 of=/dev/null bs=10 count=100000000
100000000+0 record dentro
100000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 33,4151 s, 29,9 MB/s

real    0m33.417s
user    0m5.692s
sys 0m27.624s

bs = 512 (Versetzen des Lesevorgangs, um Caching zu vermeiden)

root@iMac-Chiara:/tmp# time dd if=/dev/sda3 of=/dev/null bs=512 count=2000000 skip=6000000
2000000+0 record dentro
2000000+0 record fuori
1024000000 byte (1,0 GB) copiati, 10,7437 s, 95,3 MB/s

real    0m10.746s
user    0m0.360s
sys 0m2.428s

bs = 1k (Versetzen des Lesevorgangs, um Caching zu vermeiden)

root@iMac-Chiara:/tmp# time dd if=/dev/sda3 of=/dev/null bs=1k count=1000000 skip=6000000
1000000+0 record dentro
1000000+0 record fuori
1024000000 byte (1,0 GB) copiati, 10,6561 s, 96,1 MB/s

real    0m10.658s
user    0m0.164s
sys 0m1.772s

bs = 1k (Versetzen des Lesevorgangs, um Caching zu vermeiden)

root@iMac-Chiara:/tmp# time dd if=/dev/sda3 of=/dev/null bs=1M count=1000 skip=7000
1000+0 record dentro
1000+0 record fuori
1048576000 byte (1,0 GB) copiati, 10,7391 s, 97,6 MB/s

real    0m10.792s
user    0m0.008s
sys 0m1.144s
Damiano Verzulli
quelle
11
Was wirklich schön wäre, ist eine bs=autoFunktion dd, die den optimalen bs-Parameter des Geräts erkennt und verwendet.
4
Sehr schön wäre ein Diagramm mit mehreren bsGrößen, das anstelle von 15 Dutzend Codeblöcken in einer einzigen Frage gegen die Geschwindigkeit aufgetragen wird. Würde weniger Platz in Anspruch nehmen und unendlich schneller zu lesen sein. Ein Bild wirklich ist wert thoursand Worte.
MDMoore313
2
@BigHomie - Ich habe über die Bereitstellung eines Diagramms nachgedacht, aber ... es gibt mehrere "Skalierungs" -Probleme. Es würde wahrscheinlich eine logarithmische Skala auf beiden Achsen benötigen und ... während ich darüber nachdachte, wurde mir klar, dass es kein leichtes (und schnelles) Problem war, es zu lösen. Also bin ich auf die "Tisch" -Version umgestiegen. Was die "... 15 Dutzend Codeblöcke" betrifft, wollte ich, dass jeder die Möglichkeit hat, "rohe Zahlen" zu überprüfen, um jegliche (persönliche, meine) Störung zu vermeiden.
Damiano Verzulli
1
@DamianoVerzulli der Tisch ist cool, bitte ignoriere meine Beschimpfungen, ich habe dir trotzdem eine Belohnung für den Beweis unseres Aberglaubens gegeben, und ich weiß aus erster Hand, dass das Fummeln mit der Bytegröße die Geschwindigkeit verändern wird, ich könnte es auch in eine Antwort stecken.
MDMoore313
1
@ Warren - um 4G zu bekommen, können Sie auch tun bs=8k count=512Koder bs=1M count=4Kich erinnere mich nicht an Potenzen von 2 nach 65536
user313114

Antworten:

24

Was Sie getan haben, ist nur ein Lesegeschwindigkeitstest. Wenn Sie Blöcke tatsächlich auf ein anderes Gerät kopieren, wird der Lesevorgang unterbrochen, während das andere Gerät die zu schreibenden Daten akzeptiert. In diesem Fall kann es zu Problemen mit der Rotationslatenz auf dem Lesegerät kommen (wenn es sich um eine Festplatte handelt) Das Lesen von 1M-Abschnitten von der Festplatte ist oft erheblich schneller, da die Latenz bei der Rotation auf diese Weise seltener auftritt.

Ich weiß, dass ich beim Kopieren von Festplatten eine schnellere Rate erhalte bs=1Mals bei Verwendung von bs=4koder der Standardeinstellung. Ich spreche Geschwindigkeitsverbesserungen von 30 bis 300 Prozent. Es ist nicht nötig, es auf das absolut Beste abzustimmen, es sei denn, es ist alles, was Sie jeden Tag tun. Wenn Sie jedoch etwas Besseres als die Standardeinstellung auswählen, können Sie die Ausführungszeit um Stunden verkürzen.

Wenn Sie es wirklich verwenden, probieren Sie ein paar verschiedene Nummern aus und senden Sie dem ddProzess ein SIGUSR1Signal, damit er einen Statusbericht ausgibt, damit Sie sehen können, wie es läuft.

✗ killall -SIGUSR1 dd
1811+1 records in
1811+1 records out
1899528192 bytes (1.9 GB, 1.8 GiB) copied, 468.633 s, 4.1 MB/s
user313114
quelle
2014 Macbook Pro Retina Kopieren auf USB3-Stick mit einer Schreibgeschwindigkeit von 90 MB / s: $ sudo dd if=~/Downloads/Qubes-R4.0-rc4-x86_64.iso of=/dev/rdisk2 status=progressShows 6140928 bytes (6.1 MB, 5.9 MiB) copied, 23 s, 267 kB/s. Ich habe das abgesagt, weil es zu lange gedauert hat. Geben Sie nun die Bytesize an: $ sudo dd if=~/Downloads/Qubes-R4.0-rc4-x86_64.iso of=/dev/rdisk2 bs=1M status=progressshows4558159872 bytes (4.6 GB, 4.2 GiB) copied, 54 s, 84.4 MB/s
Eric Duncan
9

Zumindest in Bezug auf die interne Festplatte - wenn Sie vom Gerät lesen, muss die Blockschicht mindestens einen Sektor abrufen, der 512 Bytes umfasst.

Wenn Sie also einen 1-Byte-Lesevorgang ausführen, haben Sie nur wirklich von der Festplatte auf dem Sektor gelesen, auf den der Byte-Abruf ausgerichtet ist. Die verbleibenden 511 Zeiten werden vom Cache bereitgestellt.

Sie können dies wie folgt beweisen, in diesem Beispiel sdbhandelt es sich um einen interessanten Datenträger:

# grep sdb /proc/diskstats
8      16 sdb 767 713 11834 6968 13710 6808 12970792 6846477 0 76967 6853359
...
# dd if=/dev/sdb of=/dev/null bs=1 count=512
512+0 records in
512+0 records out
512 bytes (512 B) copied, 0.0371715 s, 13.8 kB/s
# grep sedb /proc/diskstats
8      16 sdb 768 713 11834 6968 13710 6808 12970792 6846477 0 76967 6853359
...

Die vierte Spalte (die die Anzahl der Lesevorgänge angibt) zeigt an, dass nur 1 Lesevorgang stattgefunden hat, obwohl Sie 1-Byte-Lesevorgänge angefordert haben. Dies ist das erwartete Verhalten, da dieses Gerät (eine SATA 2-Festplatte) mindestens seine Sektorgröße zurückgeben muss. Der Kernel cacht einfach den gesamten Sektor.

Der größte Faktor bei diesen Größenanforderungen ist der Mehraufwand beim Ausgeben eines Systemaufrufs zum Lesen oder Schreiben. Tatsächlich ist das Ausgeben des Aufrufs für <512 ineffizient. Sehr große Lesevorgänge erfordern weniger Systemaufrufe, und dafür wird mehr Speicher benötigt.

4096 ist normalerweise eine "sichere" Nummer zum Lesen, weil:

  • Beim Lesen mit aktivierter Zwischenspeicherung (Standardeinstellung) ist eine Seite 4 KB groß. Das Auffüllen einer Seite mit weniger als 4.000 Lesevorgängen ist komplizierter als das Beibehalten der Lese- und Seitengröße.
  • Die meisten Dateisystemblockgrößen sind auf 4 KB festgelegt.
  • Es ist nicht klein genug (vielleicht für SSDs), um einen Systemaufruf-Overhead zu verursachen, aber nicht groß genug, um viel Speicher zu verbrauchen.
Matthew Ife
quelle