J'ai 1000000 fichiers de 4 à 20 Ko dans un répertoire (vous pouvez générer des fichiers similaires comme ceci :seq 10000 | gzip > a; seq 1000000 | parallel --bar 'head -c{=$_=int(rand()*16)+4=}k a > {}'
)
. J'ai besoin de copier ce répertoire. Mais il semble que je doive faire une recherche pour chaque fichier donc cela prend un certain temps.
Existe-t-il un moyen d'accélérer cela ?
Je pense actuellement que si je pouvais obtenir les blocs de disque occupés par ces fichiers, je pourrais les trier, fusionner les blocs qui étaient proches (étant donné que la lecture séquentielle est souvent plus rapide que la recherche) et lire ces blocs, afin qu'ils soient en RAM cache (j'ai 32 Go de RAM) avant de faire la copie.
Mais pour que cela fonctionne, j'ai besoin d'un moyen d'identifier les blocs sur lesquels se trouvent les fichiers.
J'utilise EXT4 sur un appareil magnétique (c'est-à-dire pas un SSD).
Modifier :
Cela devrait fonctionner, mais ce n'est pas le cas :
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'
Lors du test sur un gros fichier, il ne met pas le fichier en cache.
Edit2 :
Voici quelques repères. Le cache a été vidé (echo 3 >/proc/sys/vm/drop_caches
) entre chaque course. Mesures effectuées avec 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
Alors, que pouvons-nous en apprendre ?
Il semble que le tri par inode soit une bonne idée. Mais il semble paralléliser plusieurs cp
augmente encore plus les performances. Il convient de souligner que la source foo/
est un disque magnétique, cela attaque donc le mythe selon lequel la parallélisation des E/S sur une seule broche n'accélérera pas les E/S :la parallélisation accélère clairement et systématiquement la copie ici.
Réponse acceptée :
En supposant que
- entrées renvoyées par
readdir
ne sont pas triés par numéro d'inode - la lecture des fichiers dans l'ordre des inodes réduit le nombre d'opérations de recherche
- le contenu de la plupart des fichiers est dans l'allocation initiale de 8k (une optimisation ext4) qui devrait également produire moins d'opérations de recherche
vous pouvez essayer d'accélérer la copie en copiant les fichiers dans l'ordre des inodes.
Cela signifie utiliser quelque chose comme ceci :
$ cd /mnt/src
$ ls -U -i | sort -k1,1 -n | cut -d' ' -f2- > ~/clist
$ xargs cp -t /mnt2/dst < ~/clist