Beschleunigen Sie das Kopieren von 1000000 kleinen Dateien

10

Ich habe 1000000 4-20 kb Dateien in einem Verzeichnis. Ich muss dieses Verzeichnis kopieren. Aber es scheint, dass ich nach jeder Datei suchen muss, so dass dies eine ganze Weile dauert.

Gibt es eine Möglichkeit, dies zu beschleunigen?

Ich denke derzeit, wenn ich die Plattenblöcke, die diese Dateien belegen, erhalten könnte, könnte ich diese sortieren, die geschlossenen Blöcke zusammenführen (da sequentielles Lesen oft schneller ist als Suchen) und diese Blöcke lesen, so dass sie sich im RAM befinden Cache (ich habe 32 GB RAM) vor dem Kopieren.

Damit dies funktioniert, muss ich herausfinden, auf welchen Blöcken sich die Dateien befinden.

Ich verwende EXT4 auf einem magnetischen Gerät (dh nicht SSD).

Bearbeiten:

Das sollte funktionieren, aber es funktioniert nicht:

ls |
parallel -IOO --pipe "sudo parallel -j100 hdparm --fibmap {}'|tail -n +5'" |
sort -nk 2 | 
perl -ane 'if($u+10000 < $F[1]) { print "$l ",($u-$l),"\n"; $l=$F[1] } $u=$F[2]' |
sudo parallel --colsep ' ' dd if=/dev/sda1 skip={1} bs=512 count={2} '| cat >/dev/null'

Beim Testen einer großen Datei wird die Datei nicht zwischengespeichert.

Edit2:

Hier sind einige Benchmarks. Der Cache wurde echo 3 >/proc/sys/vm/drop_cacheszwischen jedem Lauf geleert ( ). Messungen durchgeführt mit iostats -dkx 5.

rsync -Hav foo/ bar/: 1800 KB/s
cp -a foo/ bar/: 3600 KB/s
cat sort-by-inode | parallel -j1 -X cp foo/{} bar/: 5000 KB/s
cat sort-by-inode | shuf | parallel -j1 -X cp foo/{} bar/: 3000 KB/s
cat sort-by-inode | shuf | parallel -j10 -X cp foo/{} bar/: 7000 KB/s
cat sort-by-inode | parallel -j10 -X cp foo/{} bar/: 8000 KB/s
cat sort-by-inode | parallel -j100 -X cp foo/{} bar/: 9000 KB/s
cat sort-by-inode | parallel -j500 -X cp foo/{} bar/: 10000 KB/s

Was können wir daraus lernen?

Es scheint eine gute Idee zu sein, nach Inode zu sortieren. Die Parallelisierung mehrerer cpLeistungssteigerungen scheint jedoch noch weiter zu gehen. Es ist hervorzuheben, dass es sich bei der Quelle foo/um eine Magnetplatte handelt. Dies greift den Mythos an, dass das Parallelisieren von E / A zu einer einzelnen Spindel die E / A nicht beschleunigt: Das Parallelisieren beschleunigt und konsistent das Kopieren hier.

Ole Tange
quelle
Enthält Ihr Verzeichnis nur Dateien? Befindet sich Ihr Zielspeicherort im selben Dateisystem?
Joseph R.
Für den genauen Befehl, den Sie zum Kopieren verwenden? So etwas cp -r /mnt/dir1 /mnt/dirdestoder so etwas cp /mnt/dir1/* /mnt/dirdest?
Maxschlepzig
Nur Dateien, aber nicht dasselbe Dateisystem: cp -r / mnt / dir1 / mnt2 / dirdest
Ole Tange
Übrigens denke ich nicht, dass es hilfreich ist, wenn Sie Festplattenzugriffe parallel ausführen, wenn Sie die Festplattensuche minimieren möchten.
Maxschlepzig
Ich habe ein Programm geschrieben, das Dateien nach ihrer Extent-Nummer ordnet (eher das Vorkommen auf der Festplatte): github.com/nh2/diskorder
nh2

Antworten:

9

Vorausgesetzt, dass

  • Von zurückgegebene Einträge readdirwerden nicht nach Inode-Nummer sortiert
  • Das Lesen von Dateien in Inode-Reihenfolge reduziert die Anzahl der Suchvorgänge
  • Der Inhalt der meisten Dateien befindet sich in der anfänglichen 8k-Zuweisung (eine ext4-Optimierung), die auch weniger Suchoperationen ergeben sollte

Sie können versuchen, das Kopieren zu beschleunigen, indem Sie Dateien in Inode-Reihenfolge kopieren.

Das bedeutet, so etwas zu verwenden:

$ cd /mnt/src
$ ls -U -i | sort -k1,1 -n | cut -d' ' -f2- > ~/clist
$ xargs cp -t /mnt2/dst < ~/clist
maxschlepzig
quelle
@mikeserv, was meinst du? ls -Uist nicht genug, weil es nicht nach Inode-Nummern sortiert ... und warum sollte ich wollen -1?
Maxschlepzig
@mikeserv, 'in Verzeichnisreihenfolge' ist nicht dasselbe wie inode Reihenfolge! Wenn dies der Fall wäre, müssten Sie dafür kein anderes Wort verwenden. Was Sie seltsam finden, ist nicht relevant. Ich habe es sogar auf einem ext4-Dateisystem getestet. Und dort unterscheidet sich die Verzeichnisreihenfolge tatsächlich von der Inode-Reihenfolge. -1listet nur 'eine Datei pro Zeile' auf - es hilft nicht bei Zeilenumbrüchen in Dateinamen. Dafür können Sie verwenden find -print0/xargs -O.
Maxschlepzig
@mikeserv, wovon redest du? Gegenbeispiel: mkdir tmp; cd tmp; touch foo"<RETURN>"bar; lsGibt 'foo? Bar' aus. A ls -1druckt auch 'foo? Bar'. A ls -1 | wc -ldruckt '2'. A find -lsdruckt den Dateinamen als './foo\nbar'. Ein cp -i ls -1` x` schlägt mit 'cp fehl: Ziel' x 'ist kein Verzeichnis'.
Maxschlepzig
Verdammt - du bringst mir links und rechts bei! -qmacht was ich dachte -1würde! Nochmals meine Entschuldigung - ganz zu schweigen von Dank.
Mikeserv
4

GNU tar- in der paxTradition - behandelt Hardlinks selbstständig.

cd "$srcdir" ; tar --hard-dereference -cf - ./* |
    tar -C"${tgtdir}" -vxf -

Auf diese Weise haben Sie nur die beiden tarProzesse und müssen nicht immer wieder aufrufen cp.

mikeserv
quelle
2

Ähnlich wie bei der Antwort von @ maxschlepzig können Sie die Ausgabe von analysieren filefrag, um Dateien in der Reihenfolge zu sortieren, in der ihre ersten Fragmente auf der Festplatte angezeigt werden:

find . -maxdepth 1 -type f |
  xargs -d'\n' filefrag -v |
  sed -n '
    /^   0:        0../ {
      s/^.\{28\}\([0-9][0-9]*\).*/\1/
      h
      }
    / found$/ {
      s/:[^:]*$//
      H
      g
      s/\n/ /p
      }' |
    sort -nk 1,1 |
    cut -d' ' -f 2- |
    cpio -p dest_dir

MMV mit dem obigen sedSkript, also stellen Sie sicher, dass Sie es gründlich testen.

Andernfalls ist filefrag(ein Teil von e2fsprogs) , was auch immer Sie tun, viel schneller zu verwenden, als hdparmes mehrere Dateiargumente annehmen kann. Allein der Overhead, hdparm1.000.000 Mal ausgeführt zu werden, wird viel Overhead verursachen.

Außerdem wäre es wahrscheinlich nicht so schwierig, für jede Datei ein perlSkript (oder C-Programm) zu schreiben FIEMAP ioctl, ein sortiertes Array der zu kopierenden Blöcke und der dazugehörigen Dateien zu erstellen und dann alles in der richtigen Reihenfolge zu kopieren Lesen Sie die Größe jedes Blocks aus der entsprechenden Datei (achten Sie jedoch darauf, dass Ihnen nicht die Dateideskriptoren ausgehen).

Graeme
quelle
Dies ist schön, siehe auch home.ifi.uio.no/paalh/publications/files/ipccc09.pdf für ein Dokument , das den Ansatz beschreibt und eine ~ 4-fache Beschleunigung tarfür ihre Dateien zeigt.
nh2
1
Ich habe die Autoren des Papiers per E-Mail gefragt, ob sie qtarals Open Source veröffentlicht werden könnten . es ist jetzt bei github.com/chlunde/qtar
nh2