Eu tenho 1000000 arquivos de 4-20 kb em um diretório. Eu preciso copiar esse diretório. Mas parece que eu tenho que procurar cada arquivo, então isso leva um bom tempo.
Existe uma maneira de acelerar isso?
Atualmente, estou pensando que, se eu pudesse obter os blocos de disco que esses arquivos ocupam, poderia classificá-los, mesclar os que estavam próximos (considerando que a leitura seqüencial geralmente é mais rápida do que a busca) e ler esses blocos, para que eles estivessem na RAM cache (tenho 32 GB de RAM) antes de fazer a cópia.
Mas, para que isso funcione, preciso de uma maneira de identificar em quais blocos os arquivos estão.
Estou usando EXT4 em um dispositivo magnético (ou seja, não SSD).
Editar:
Isso deve funcionar, mas não:
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'
Ao testá-lo em um arquivo grande, ele não o armazena em cache.
Edit2:
Aqui estão alguns benchmarks. O cache foi liberado ( echo 3 >/proc/sys/vm/drop_caches
) entre cada execução. Medições feitas com 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
Então, o que podemos aprender com isso?
Parece que classificar por inode é uma boa ideia. Mas parece que paralelizar múltiplos cp
impulsiona ainda mais o desempenho. Vale ressaltar que a fonte foo/
é um disco magnético; portanto, isso ataca o mito de que a E / S paralela a um único eixo não acelera a E / S: a paralelização clara e consistente acelera a cópia aqui.
cp -r /mnt/dir1 /mnt/dirdest
ou algo parecido cp /mnt/dir1/* /mnt/dirdest
?