У меня 1000000 файлов 4-20 кб в каталоге. Мне нужно скопировать этот каталог. Но, похоже, мне нужно искать каждый файл, так что это занимает довольно много времени.
Есть ли способ, которым я могу ускорить это?
В настоящее время я думаю, что, если бы я мог получить блоки дисков, которые занимают эти файлы, я мог бы отсортировать их, объединить блоки, которые были близки (учитывая, что последовательное чтение часто быстрее, чем поиск) и прочитать эти блоки, чтобы они были в оперативной памяти кеш (у меня 32 гб оперативки) перед выполнением копирования.
Но чтобы это работало, мне нужен способ определить, на каких блоках находятся файлы.
Я использую EXT4 на магнитном устройстве (т.е. не SSD).
Редактировать:
Это должно работать, но это не так:
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'
При тестировании большого файла он не кэширует файл.
Edit2:
Вот несколько ориентиров. Кэш сбрасывался ( echo 3 >/proc/sys/vm/drop_caches
) между каждым запуском. Измерения сделаны с 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
Так что мы можем извлечь из этого?
Кажется, сортировка по индоду - хорошая идея. Но кажется, что распараллеливание нескольких cp
увеличивает производительность еще дальше. Стоит подчеркнуть, что источником foo/
является магнитный диск, поэтому нападает на миф о том, что распараллеливание ввода-вывода с одним шпинделем не ускорит ввод-вывод: распараллеливание четко и последовательно ускоряет копирование здесь.
cp -r /mnt/dir1 /mnt/dirdest
или что-то вроде cp /mnt/dir1/* /mnt/dirdest
?