Ускорьте копирование 1000000 маленьких файлов

11

У меня 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?
maxschlepzig
Только файлы, но не та же файловая система: cp -r / mnt / dir1 / mnt2 / dirdest
Ole Tange
Кстати, я не думаю, что это помогает, если вы выполняете доступ к жесткому диску параллельно, когда вы хотите минимизировать количество обращений к диску.
maxschlepzig
Я написал программу, которая упорядочивает файлы по их номеру
экстента

Ответы:

9

При условии, что

  • возвращаемые записи readdirне сортируются по номеру инода
  • чтение файлов в порядке индекса уменьшает количество операций поиска
  • содержимое большинства файлов находится в начальном распределении 8 Кб (оптимизация ext4), что также должно привести к меньшему количеству операций поиска

Вы можете попытаться ускорить копирование путем копирования файлов в порядке следования узлов.

Это значит использовать что-то вроде этого:

$ cd /mnt/src
$ ls -U -i | sort -k1,1 -n | cut -d' ' -f2- > ~/clist
$ xargs cp -t /mnt2/dst < ~/clist
maxschlepzig
источник
@mikeserv, что ты имеешь в виду? ls -Uнедостаточно, потому что не сортирует по номерам инодов ... а зачем мне хотеть -1?
maxschlepzig
@mikeserv, 'в порядке каталогов' не совпадает с порядком инодов! Если бы это было так, вам не пришлось бы использовать другое слово для этого. То, что вы находите странным, не имеет значения. Я даже протестировал его на файловой системе ext4. И там порядок каталогов действительно отличается от порядка инодов. -1просто перечисляет «один файл на строку» - это не помогает с новыми строками в именах файлов. Для этого вы можете использовать find -print0/xargs -O.
maxschlepzig
@mikeserv, о чем ты говоришь? Встречный пример: mkdir tmp; cd tmp; touch foo"<RETURN>"bar; lsпечатает 'foo? Bar'. А ls -1также печатает «foo? Bar». А ls -1 | wc -lпечатает «2». A find -lsпечатает имя файла как «./foo\nbar». cp -i Ls -1` x` терпит неудачу с "ф: мишень„х“не является каталогом.
maxschlepzig
Блин - ты учишь меня направо и налево! -qделает то, что я думал, -1будет! Опять же, мои извинения - не говоря уже о спасибо.
mikeserv
4

GNU tar- по paxтрадиции - обрабатывает жесткие ссылки самостоятельно.

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

Таким образом, у вас есть только два tarпроцесса, и вам не нужно cpповторять вызовы снова и снова.

mikeserv
источник
2

Аналогично ответу @ maxschlepzig , вы можете анализировать выходные данные filefragдля сортировки файлов в порядке появления их первых фрагментов на диске:

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 с приведенным выше sedсценарием, поэтому обязательно тщательно протестируйте.

В противном случае, что бы вы ни делали, filefrag(часть e2fsprogs) будет гораздо быстрее использовать, чем, hdparmпоскольку он может принимать несколько файловых аргументов. Только накладные расходы на запуск hdparm1000000 раз добавят много накладных расходов.

Также, вероятно, было бы не так сложно написать perlскрипт (или программу на C) FIEMAP ioctlдля каждого файла, создать отсортированный массив блоков, которые должны быть скопированы, и файлы, к которым они принадлежат, и затем скопировать все по порядку: Чтение размера каждого блока из соответствующего файла (будьте осторожны, чтобы не исчерпать дескрипторы файлов).

Graeme
источник
Это хорошо, см. Также home.ifi.uio.no/paalh/publications/files/ipccc09.pdf для статьи, которая описывает подход и показывает ускорение в ~ 4 раза tarдля их файлов.
nh2
1
Я написал авторам статьи по электронной почте, спрашивая, могут ли они выпустить их qtarс открытым исходным кодом; сейчас на github.com/chlunde/qtar
nh2