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.
fonte
cp -r /mnt/dir1 /mnt/dirdest
ou algo parecidocp /mnt/dir1/* /mnt/dirdest
?Respostas:
Assumindo que
readdir
não são classificadas pelo número do inodevocê pode tentar acelerar a cópia via copiar arquivos em ordem de inode.
Isso significa usar algo como isto:
fonte
ls -U
não é suficiente porque não classifica por números de inode ... e por que devo querer-1
?-1
apenas lista 'um arquivo por linha' - não ajuda com novas linhas nos nomes de arquivos. Para isso você pode usarfind -print0/xargs -O
.mkdir tmp; cd tmp; touch foo"<RETURN>"bar; ls
imprime 'foo? Bar'. Als -1
também imprime 'foo? Bar'. Als -1 | wc -l
imprime '2'. Afind -ls
imprime o nome do arquivo como './foo\nbar'. Umcp -i
ls -1` x` falha com 'cp: target' x 'não é um diretório'.-q
faz o que eu pensei que-1
faria! Mais uma vez, minhas desculpas - para não mencionar obrigado.O GNU
tar
- napax
tradição - lida com hardlinks por conta própria.Dessa forma, você só tem os dois
tar
processos e não precisa continuar invocandocp
repetidamente.fonte
Da mesma forma que a resposta de @ maxschlepzig , você pode analisar a saída de
filefrag
para classificar arquivos na ordem em que seus primeiros fragmentos aparecem no disco:MMV com o
sed
script acima , portanto, teste-o minuciosamente.Caso contrário, o que você fizer
filefrag
(parte dee2fsprogs
) será muito mais rápido de usar dohdparm
que pode receber vários argumentos de arquivo. Apenas a sobrecarga de executarhdparm
1.000.000 de vezes adicionará muita sobrecarga.Além disso, provavelmente não seria tão difícil escrever um
perl
script (ou programa C), para umFIEMAP
ioctl
arquivo para cada, criar uma matriz classificada dos blocos que devem ser copiados e dos arquivos aos quais pertencem e copiar tudo em ordem, lendo o tamanho de cada bloco no arquivo correspondente (tenha cuidado para não ficar sem os descritores de arquivos).fonte
tar
para seus arquivos.qtar
como código aberto; agora é a github.com/chlunde/qtar