Faux pas: «Быстрый» метод, о котором я упоминал ниже, не в 60 раз быстрее медленного. Это в 30 раз быстрее. Я буду обвинять ошибку в часе (3 утра не лучшее время дня для ясного мышления 🙂 ..
Обновление: я добавил сводку времени тестирования (см. Ниже).
Кажется, есть два вопроса, связанных с коэффициентом скорости:
Все тесты были выполнены с 1 миллионом файлов.
(реальные, пользовательские и sys-времена находятся в тестовых сценариях)
Сценарии тестирования можно найти на странице paste.ubuntu.com
# # 1 million files # =============== # # |time |new dir |Files added in ASCENDING order # +---- +------- +------------------------------------------------- # real 01m 33s Add files only (ASCENDING order) ...just for ref. # real 02m 04s Add files, and make 'rm' source (ASCENDING order) # Add files, and make 'rm' source (DESCENDING order) # real 00m 01s Count of filenames # real 00m 01s List of filenames, one per line # ---- ------- ------ # real 01m 34s 'rm -rf dir' # real 01m 33s 'rm filename' via rm1000filesPerCall (1000 files per 'rm' call) # real 01m 40s 'rm filename' via ASCENDING algorithm (1000 files per 'rm' call) # real 01m 46s 'rm filename' via DESCENDING algorithm (1000 files per 'rm' call) # real 21m 14s 'rm -r dir' # real 21m 27s 'find dir -name "hello*" -print0 | xargs -0 -n 1000 rm' # real 21m 56s 'find dir -name "hello*" -delete' # real 23m 09s 'find dir -name "hello*" -print0 | xargs -0 -P 0 rm' # real 39m 44s 'rm filename' (one file per rm call) ASCENDING # real 47m 26s 'rm filename' (one file per rm call) UNSORTED #
Недавно я создал и удалил 10 миллионов пустых тестовых файлов. Удаляя файлы по имени по имени (т. rm filename
), я обнаружил, что существует трудная разница между двумя разными способами …
Оба метода используют ту же самую команду rm filename
.
Обновление: как оказалось, команды были не совсем одинаковыми … Один из них отправлял 1000 имен файлов одновременно в «rm» … Это была проблема расширения расширений оболочки, в которой я думал, что каждое имя файла написано к файлу фидера на отдельной строке, но на самом деле это было 1000 на строку
Имена файлов предоставляются через «файл фидера» в цикл while read
while.
Файл фидера – это выход ls -1 -f
Методы идентичны во всех аспектах, за исключением одного:
ls -1 -f
Я не уверен, что здесь проблема сортировки, или возможно, что отсортированный файл фидера просто соответствует последовательности, в которой были созданы файлы (я использовал простой восходящий целочисленный алгоритм)
Для 1 миллиона файлов метод быстрого rm filename
в 60 раз быстрее, чем медленный метод … опять же, я не знаю, является ли это проблемой сортировки или проблемой хэш-таблицы за кадром … Я подозреваю, что это не простая проблема сортировки, потому что почему ls -1 -f
преднамеренно дает мне несортированный список недавно добавленной «отсортированной» последовательности имен файлов …
Мне просто интересно, что здесь происходит, поэтому мне не нужны дни (да дни), чтобы удалить следующие 10 миллионов файлов 🙂 …. Я говорю «дни», потому что я пробовал так много альтернатив, и в разы увеличилось непропорционально количество задействованных файлов. Поэтому я только проверил 1 млн. подробностей
BTW: Удаление файлов через «отсортированный список» имен на самом деле быстрее, чем rm -rf
, в 2 раза.
и: rm -r
был в 30 раз медленнее, чем метод «отсортированного списка»
… но «отсортирован» здесь? или он больше связан с хешированием (или каким-либо другим) методом хранения, используемым ext4?
Меня совершенно озадачивает то, что каждый вызов rm filename
имеет отношения к предыдущему .. (ну, по крайней мере, так происходит с точки зрения «bash»)
Я использую Ubuntu / bash / 'ext4' / SATA II.
Ожидается, что rm -r будет медленным, как рекурсивный. Первой обход глубины должен быть сделан в структуре каталогов.
Теперь, как вы создали 10 миллионов файлов? использовал ли у вас какой-нибудь скрипт, который в каком порядке? 1.txt, 2.txt, 3.txt … если да, то эти файлы также могут быть выделены в том же порядке в смежных блоках в hdd.so удалении в том же порядке будет быстрее.
«ls -f» включит -aU, который перечисляет в порядке каталога, который снова рекурсивен.
Вы должны оптимизировать структуру. Поэтому вместо
for i in $(seq 1 1000); do touch file.$i; done
сделайте что-нибудь умнее (предположим bash):
function bucklocate() { hash=$(echo -n "$1"|md5sum|cut -f1); echo -n "${hash:1:1}/${hash:7:1}/${hash:9:2}/$1"; } hexdig="{0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f}" eval mkdir -p $hexdig/$hexdig/$hexdig$hexdig for i in $(seq 1 1000); do touch $(bucklocate file.$i); done
Теперь этот пример довольно медленный из-за использования md5sum [1], используйте что-то вроде следующего для гораздо более быстрого ответа, если вам не нужны какие-либо имена файлов, дубликаты не имеют значения, и нет необходимости в повторяемый хеш определенного имени 🙂
mkdir -pv {0,1,2,3,4,5,6}/{0,1,2,3,4,5,6,7,8,9,10,12} for a in $(seq 1 100); do i=$RANDOM; echo touch "$(($i%7))/$(($i%13))/file.$i"; done
Конечно, это все небрежно заимствует понятия из хэш-таблиц