Warum schreibt dd direkt langsamer auf die Festplatte als in eine Datei?

7

Ich versuche, die aggregierten Schreibraten beim Schreiben in eine Datei in einem GPFS-Dateisystem im Vergleich zum direkten Schreiben auf eine Festplatte auf einem System mit Red Hat Enterprise Linux Server Version 6.4 (Santiago) zu vergleichen. Für meine Anwendung muss ich die Rohrate messen, dh ohne den Cache zu nutzen. Ich verstehe die Auswirkungen der direkten Option ddzum Umgehen des Caches nicht. Wenn ich direkt auf ein Blockgerät schreibe, erhalte ich bei der Verwendung eine drastisch niedrigere Rate als oflag=directbeim Schreiben in eine Datei im GPFS-Dateisystem. Warum passiert das?

Um die Gesamtraten zu messen, erstelle ich pProzesse dd, die gleichzeitig in das Blockgerät oder die Blockdatei schreiben. Ich summiere dann die erhaltenen pRaten, um die aggregierte Schreibrate zu erhalten.

    #!/bin/bash
    directdiskrate=~/scratch/rate5
    syncdiskrate=~/scratch/rate4
    filerate=~/scratch/rate3
    numruns=1
    numthreads=30

    #to disk use both conv=fsync and oflag=direct
    writetodiskdirect="dd if=/dev/zero of=/dev/sdac bs=256k count=4096 conv=fsync oflag=direct iflag=fullblock"
    for p in $(seq $numthreads)
    do
             #parses output of dd, rate is on last line, each field separated by ,s
            $writetodiskdirect 2>&1|tail -n 1|awk 'BEGIN { FS = "," } ; { print $3 }'|sed -e 's/MB\/s//g'>>$directdiskrate&
    done
    wait

    #to disk use only conv=fsync option
    writetodisksync="dd if=/dev/zero of=/dev/sdac bs=256k count=4096 conv=fsync iflag=fullblock"
    for p in $(seq $numthreads)
    do
       #parses output of dd, rate is on last line, each field separated by ,s
       $writetodisksync 2>&1|tail -n 1|awk 'BEGIN { FS = "," } ; { print $3 }'|sed -e 's/MB\/s//g'>>$syncdiskrate&
    done
    wait

    #to file use both conv=fsync and oflag=direct
    for p in $(seq $numthreads)
    do
        writetofile="dd if=/dev/zero of=/gpfs1/fileset6/file$p bs=256k count=4096 conv=fsync oflag=direct"
        #parses output of dd, rate is on last line, each field separated by ,s
        $writetofile 2>&1|tail -n 1|awk 'BEGIN { FS = "," } ; { print $3 }'|sed -e 's/MB\/s//g'>>$filerate&
    done
    wait

Ergebnisse: Die Schreibrate jedes der 30 Prozesse ist wie folgt:

  1. Beim Schreiben auf die Festplatte mit der conv=fsyncOption erhält jeder Prozess eine Schreibrate von ~ 180 MB / s
  2. Beim Schreiben auf die Festplatte mit beiden conv=fsyncund oflag=directerhält jeder Prozess eine Schreibrate von ~ 9 MB / s
  3. Das Schreiben in eine Datei im GPFS-Dateisystem mit beiden conv=fsyncund oflag=directerzielt eine Schreibrate von ~ 80 MB / s
user3216949
quelle
Haben Sie es geschafft, eine Kombination von Flags zu finden, die dazu führt, dass das Schreiben in eine Datei (über die Dateisystemschicht) durchweg langsamer ist als das direkte Schreiben auf das Blockgerät? fsync scheint auf einigen Dateisystemtypen zu funktionieren, aber bei Verwendung von FUSE exfat scheint es immer noch zwischenzuspeichern.
Austinmarton

Antworten:

5

Dieser Unterschied beruht zweifellos auf einer Sache: dem Caching.

Es wird wirklich schwierig sein, genau zu bestimmen, wo, insbesondere aus dem Userland, aber alle Linux-Kernel-Puffer (Cache) -Dateisystem-Schreibvorgänge ausgeführt werden, es sei denn, Sie führen die Tricks aus, um synchrone Schreibvorgänge zu erhalten. Das heißt, der Kernel speichert die ddgesendeten Daten in einer Datei irgendwo im Kernelspeicher. Der Kernel verwendet dazu wahrscheinlich Dateisystemcode. Irgendwann in der Zukunft plant der Kernel einen Festplattenblock, der auf die Festplatte übertragen werden soll. Dies geschieht "asynchron", irgendwann nachdem der Kernel mitgeteilt hat, dddass der Schreibvorgang abgeschlossen ist.

Der Grund dafür ist, dass das Verschieben von Bytes über einen Bus und in ein Festplattenlaufwerk und dann auf die Festplattenplatten viel langsamer ist als das Kopieren vom Benutzer in den Kernelspeicher. Normalerweise ist es Programmen egal, dass die Daten, die sie gerade "geschrieben" haben, für eine Weile nicht auf die Festplatte gelangen. Die Hardware-Zuverlässigkeit ist hoch genug, damit die Daten fast immer plattiert werden können.

Das ist die einfache Antwort, aber sobald Sie alle im Kernel gepufferten Dateien gelesen / geschrieben / gelöscht haben, kann der Dateisystemcode die kurze Lebensdauer der Dateien nutzen, indem er niemals die Daten von Dateien ausschreibt, die gelöscht werden, bevor sie es schaffen Platte. Der Dateisystemcode kann Schreibvorgänge gruppieren, um Festplattenblöcke zu nutzen, die größer als eine Gruppe von Schreibvorgängen sind, und sie zu einem Schreibvorgang zusammenfassen. In den meisten Dateisystemen können unzählige Optimierungen vorgenommen werden.

Bruce Ediger
quelle
Bedeutet dies, dass trotz der Verwendung der Option oflag = direct mit der Datei dd write to file der Schreibvorgang weiterhin über den Cache erfolgt? Aber das oflag = direct wird wirklich wirksam, wenn direkt auf ein Blockgerät geschrieben wird?
user3216949
@ user3216949 - Ich denke das ist wahr, aber ich habe kein direktes Wissen. Das Blockgerät befindet sich am Ende des Benutzers -> Kernel -> Dateisystem -> Festplattenschichten. Soweit ich weiß, werden durch die Verwendung des Blockgeräts die Dateisystemschicht (en) im Stapel entfernt.
Bruce Ediger
@ Bruce gibt es eine Möglichkeit (wie ein Tool) zu überprüfen, ob die Schreibvorgänge den Cache durchlaufen oder nicht?
Felix
@ user3216949 Wenn Sie sicherstellen möchten, dass die Daten tatsächlich auf die Festplatte geschrieben werden, verwenden Sie eine der folgenden Optionen : conv=fdatasync conv=fsync oflag=dsync oflag=sync.
Patrick
2

Das Festplatten-Cache von Kopierprogrammen macht es schneller als die Verwendung von dd, würde ich annehmen.

Wenn dies die einzige festplattenintensive App ist, die ausgeführt wird, warten Sie, bis das Programm beendet ist, und führen Sie dann Folgendes aus:

$ sync; sync 

Dadurch wird der Cache sofort geleert. Wenn es eine Weile dauert, bis Sie zur Eingabeaufforderung zurückkehren, wissen Sie, dass sie den Cache erreicht hat.

Ich mache das, bevor ich meine USB-Laufwerke ziehe, und es dauert oft ziemlich lange, bis die Kopie fertig ist und der Cache auf die Festplatte gelangt.

rking
quelle
Vielen Dank, ich habe anhand Ihres Vorschlags festgestellt, dass selbst bei Verwendung von fsync Daten auf die Festplatte geschrieben werden, aber möglicherweise effizienter als ein Massenschreiben.
user3216949
0

Die Antwort darauf kann kompliziert sein. O_DIRECTist eher ein Hinweis als eine Bestellung und Dateisysteme dürfen sie unter Linux ignorieren und nur den Puffercache verwenden. Gemäß " Überlegungen zur Verwendung von direkter E / A (O_DIRECT) für GPFS-Anwendungen " kann GPFS auf einen gepufferten Betrieb (gefolgt von einem O_SYNC) zurückgreifen, wenn die Dinge nicht perfekt sind. Im Szenario des Fragestellers kann Folgendes zutreffen:

Durch das Schreiben wird die Datei größer.

Wir können nicht sagen, ob dddie Datei (en) erweitert wurde. Wenn dies der Fall war, durchlief die E / A den Puffercache im Fall des Dateisystems und NICHT im Fall des direkten Blockiergeräts.

Anon
quelle