Ich habe 1000000 4-20-KB-Dateien in einem Verzeichnis (Sie können ähnliche Dateien wie folgt generieren:seq 10000 | gzip > a; seq 1000000 | parallel --bar 'head -c{=$_=int(rand()*16)+4=}k a > {}'
)
. Ich muss dieses Verzeichnis kopieren. Aber es scheint, dass ich für jede Datei eine Suche durchführen muss, also dauert das eine ganze Weile.
Gibt es eine Möglichkeit, dies zu beschleunigen?
Ich denke derzeit, wenn ich die Festplattenblöcke erhalten könnte, die diese Dateien belegen, könnte ich diese sortieren, die Blöcke zusammenführen, die nahe beieinander liegen (da sequenzielles Lesen oft schneller ist als das Suchen) und diese Blöcke lesen, sodass sie sich im RAM befinden Cache (ich habe 32 GB RAM) vor dem Kopieren.
Aber damit das funktioniert, brauche ich eine Möglichkeit zu identifizieren, in welchen Blöcken sich die Dateien befinden.
Ich verwende EXT4 auf einem magnetischen Gerät (d. h. nicht SSD).
Bearbeiten:
Das sollte funktionieren, tut es aber 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 mit einer großen Datei wird die Datei nicht zwischengespeichert.
Edit2:
Hier sind einige Benchmarks. Cache wurde geleert (echo 3 >/proc/sys/vm/drop_caches
) zwischen jedem Lauf. 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, dass das Sortieren nach Inodes eine gute Idee ist. Aber es scheint, mehrere cp
zu parallelisieren steigert die Leistung noch weiter. Es sollte betont werden, dass die Quelle foo/
ist eine Magnetplatte, also greift dies den Mythos an, dass das Parallelisieren von I/O auf eine einzelne Spindel die I/O nicht beschleunigt:Parallelisieren beschleunigt hier eindeutig und konsistent das Kopieren.
Akzeptierte Antwort:
Vorausgesetzt,
- Einträge, die von
readdir
zurückgegeben werden sind nicht nach Inode-Nummer sortiert - Das Lesen von Dateien in der Inode-Reihenfolge reduziert die Anzahl der Suchvorgänge
- Der Inhalt der meisten Dateien befindet sich in der anfänglichen 8k-Zuordnung (eine ext4-Optimierung), was auch zu weniger Suchvorgängen führen sollte
Sie können versuchen, das Kopieren zu beschleunigen, indem Sie die Dateien in der 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