Velocizza la copia di 1000000 piccoli file


11

Ho 1000000 file da 4-20 kb in una directory. Devo copiare quella cartella. Ma sembra che devo fare una ricerca per ogni file, quindi ci vuole un po 'di tempo.

C'è un modo in cui posso accelerarlo?

Attualmente sto pensando che se potessi ottenere i blocchi del disco che occupano questi file, potrei ordinarli, unire i blocchi che erano vicini (dato che la lettura sequenziale è spesso più veloce della ricerca) e leggere questi blocchi, in modo che fossero nella RAM cache (ho 32 GB di RAM) prima di fare la copia.

Ma affinché funzioni, ho bisogno di un modo per identificare su quali blocchi si trovano i file.

Sto usando EXT4 su un dispositivo magnetico (cioè non SSD).

Modificare:

Questo dovrebbe funzionare ma non:

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'

Durante il test su un file di grandi dimensioni, non memorizza nella cache il file.

Edit2:

Ecco alcuni parametri di riferimento. La cache è stata svuotata ( echo 3 >/proc/sys/vm/drop_caches) tra ogni esecuzione. Misure effettuate con 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

Quindi cosa possiamo imparare da quello?

Sembra che l'ordinamento per inode sia una buona idea. Ma sembra che la parallelizzazione multipla cpaumenti ulteriormente le prestazioni. Vale la pena sottolineare che la sorgente foo/è un disco magnetico, quindi questo attacca il mito secondo cui parallelizzare l'I / O su un singolo mandrino non accelera l'I / O: parallelizzare in modo chiaro e coerente accelera la copia qui.


La tua directory contiene solo file? La posizione di destinazione è sullo stesso filesystem?
Joseph R.,

Per il comando esatto che stai usando per la copia? Qualcosa di simile cp -r /mnt/dir1 /mnt/dirdesto qualcosa di simile cp /mnt/dir1/* /mnt/dirdest?
maxschlepzig,

Solo file ma non lo stesso filesystem: cp -r / mnt / dir1 / mnt2 / dirdest
Ole Tange

btw, non penso che sia utile se si eseguono gli accessi al disco rigido in parallelo quando si desidera ridurre al minimo le ricerche del disco.
maxschlepzig,

Ho scritto un programma che ordina i file in base al loro numero di estensione (più probabile che si verifichi sul disco) qui: github.com/nh2/diskorder
nh2

Risposte:


9

Supponendo che

  • le voci restituite da readdirnon sono ordinate per numero di inode
  • la lettura dei file in ordine di inode riduce il numero di operazioni di ricerca
  • il contenuto della maggior parte dei file è nell'allocazione 8k iniziale (un'ottimizzazione ext4) che dovrebbe anche produrre meno operazioni di ricerca

puoi provare ad accelerare la copia copiando i file in ordine di inode.

Ciò significa usare qualcosa del genere:

$ cd /mnt/src
$ ls -U -i | sort -k1,1 -n | cut -d' ' -f2- > ~/clist
$ xargs cp -t /mnt2/dst < ~/clist

@mikeserv, che vuoi dire? ls -Unon è sufficiente perché non ordina per numeri di inode ... e perché dovrei volerlo -1?
maxschlepzig,

@mikeserv, 'nell'ordine di directory' non è uguale all'ordine di inode! Se così fosse, non dovresti usare una parola diversa per questo. Ciò che trovi strano non è rilevante. L'ho anche testato su un filesystem ext4. E lì l'ordine delle directory è davvero diverso dall'ordine degli inode. -1elenca solo 'un file per riga' - non aiuta con le nuove righe nei nomi dei file. Per quello puoi usare find -print0/xargs -O.
maxschlepzig,

@mikeserv, di cosa stai parlando? Contro esempio: mkdir tmp; cd tmp; touch foo"<RETURN>"bar; lsstampa 'foo? Bar'. A ls -1stampa anche 'foo? Bar'. A ls -1 | wc -lstampa "2". A find -lsstampa il nome file come './foo\nbar'. A cp -i ls -1` x` fallisce con 'cp: target' x 'non è una directory'.
maxschlepzig,

Accidenti - mi stai insegnando a destra e a sinistra! -qfa quello che pensavo -1sarebbe! Ancora una volta, mi scuso - per non parlare grazie.
Mikeserv,

4

GNU tar- nella paxtradizione - gestisce da solo gli hardlink.

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

In questo modo hai solo i due tarprocessi e non hai bisogno di continuare a invocare cpancora e ancora.


2

Analogamente alla risposta di @ maxschlepzig , è possibile analizzare l'output di filefragordinare i file nell'ordine in cui i loro primi frammenti appaiono sul disco:

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 con lo sedscript sopra , quindi assicurati di testare a fondo.

Altrimenti, qualunque cosa tu faccia, filefrag(parte di e2fsprogs) sarà molto più veloce da usare di hdparmquanto possa accettare più argomenti di file. Solo l'overhead della corsa hdparm1.000.000 di volte aggiungerà un sacco di overhead.

Inoltre, probabilmente non sarebbe così difficile scrivere uno perlscript (o un programma C) in un FIEMAP ioctlfile per ogni file, creare un array ordinato dei blocchi che dovrebbero essere copiati e dei file a cui appartengono e quindi copiare tutto in ordine per leggere la dimensione di ciascun blocco dal file corrispondente (fare attenzione a non esaurire i descrittori di file).


Questo è carino, vedi anche home.ifi.uio.no/paalh/publications/files/ipccc09.pdf per un documento che descrive l'approccio e mostra una velocità di ~ 4x tarper i loro file.
nh2,

1
Ho inviato un'e-mail agli autori dell'articolo, chiedendo se potevano essere rilasciati qtarcome open source; è ora su github.com/chlunde/qtar
nh2
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.