Почему удаление файлов по имени мучительно медленно, а также исключительно быстро?

11

Подделка: «быстрый» метод, о котором я упоминаю ниже, не в 60 раз быстрее медленного. Это в 30 раз быстрее. Я обвиню ошибку в час (3 утра не лучшее время для ясного мышления :) ..

Обновление: я добавил сводку времени испытаний (ниже).
Кажется, есть две проблемы, связанные с фактором скорости:

  • Выбор используемой команды (сравнение времени показано ниже)
  • Природа большого количества файлов в каталоге ... Кажется, что "большой это плохо". Вещи становятся непропорционально медленнее с ростом числа.

Все тесты были выполнены с 1 миллионом файлов.
(реальное, пользовательское и системное время указано в тестовых сценариях)
. Тестовые сценарии можно найти по адресу 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цикл.
Файл фидера является выходом ls -1 -f
методов во всех отношениях идентичны, за исключением одного:

  • медленный метод использует несортированный фидер файл прямо изls -1 -f
  • быстрый метод использует отсортированный версию того же файла несортированным

Я не уверен, является ли сортировка этой проблемой здесь, или, возможно, что отсортированный файл фидера просто соответствует последовательности, в которой были созданы файлы (я использовал простой целочисленный алгоритм возрастания)

Для 1 миллиона файлов быстрый rm filename метод в 60 раз быстрее, чем медленный метод ... опять же, я не знаю, является ли это проблемой "сортировки", или проблемой закулисной хэш-таблицы ... Я подозреваю, это не простая проблема сортировки, потому что зачем ls -1 -fнамеренно давать мне несортированный список недавно добавленной «отсортированной» последовательности имен файлов ...

Мне просто интересно, что здесь происходит, поэтому мне не нужно дней (да дней), чтобы удалить следующие 10 миллионов файлов :) .... Я говорю "дни", потому что я пробовал так много альтернатив, и количество раз увеличивается непропорционально количеству задействованных файлов ... так что я только детально протестировал 1 миллион

Кстати: удаление файлов через «отсортированный список» имен на самом деле быстрее, чем rm -rfв 2 раза,
а: rm -rбыло в 30 раз медленнее, чем метод «отсортированный список»

... но "отсортирован" проблема здесь? или это больше связано с хеширующим (или каким-либо другим) методом хранения, используемым ext4?

Меня удивляет то, что каждый вызов rm filenameне связан с предыдущим ... (по крайней мере, это так с точки зрения bash)

Я использую диск Ubuntu / bash / 'ext4' / SATA II.

Peter.O
источник
1
Ты делаешь это неправильно! (тм) Когда-нибудь слышали о find -delete?
Алекс
Ваши 2 теста начинаются в неравных условиях (я не претендую на то, что это действительно важно): один читает имена файлов из файла, а другой читает имена файлов из файла, который был создан (отсортирован) непосредственно перед тестом. Может случиться так, что файл, кэшируемый во втором случае, воспроизводит некоторые данные (или, может быть, нет, кто знает). Чтобы тесты находились в более равных условиях, возможно, вам следует сделать простой catи свежий файл до 1-го теста - вместо sortдо 2-го теста.
imz - Иван Захарящев
И я рекомендую вам представить ваши наблюдения и ваш вопрос в более четкой форме. Пожалуйста, по одному за раз: сравните только 2 случая в одном вопросе, перенесите два важных случая на второй план, все остальные - просто справочная информация; пожалуйста, сделайте это ясно. Не смешивайте несколько наблюдений в одной публикации, пожалуйста.
imz - Иван Захарящев
Представление системы и времени пользователя из вашего пространства также может быть важно для решения головоломки, поэтому, пожалуйста, включите их в свой вопрос. Какой из них имеет большое значение в ваших тестах?
imz - Иван Захарящев
1
Преждевременная оптимизация - корень всего зла. :) Когда ты когда-нибудь удалишь 10 миллионов файлов? 100 000 в секунду мне кажется достаточно быстрым (чтобы разрушить вашу систему).
пользователь неизвестен

Ответы:

2

Ожидается, что rm -r будет медленным как рекурсивный. Первый глубокий обход должен быть сделан в структуре каталогов.

Теперь, как вы создали 10 миллионов файлов? Вы использовали какой-нибудь скрипт, который зацикливается на каком-то порядке? 1.txt, 2.txt, 3.txt ... если да, то эти файлы могут быть расположены в одном и том же порядке в последовательных блоках в hdd.so удаление в том же порядке будет быстрее.

«ls -f» включит -aU, который перечисляет в порядке каталога, который снова рекурсивен.

rajaganesh87
источник
1
Макалот: Я не понимаю, как «рекурсивный» имеет значение в этом случае , так как в нем нет подкаталогов ... Да, я использовал «1.txt, 2.txt, 3.txt». Возможно, есть несколько вещи, которые взаимодействуют: например, Почему создание 1 миллиона файлов занимает всего 1 мин 30 с, а создание 2 млн - 7 м 10 с, а после их удаления воссоздание 1 млн намного дольше (9 м 30 с) становится странным; все работает медленно, внезапно. Это уже происходило раньше. Я думаю (?) удаление каталога исправило его. Возможно, задействован файловый демон (nautilus; locate)? Продолжение следует ...
Peter.O
В общем, файловые системы не оптимизированы для работы с большим количеством файлов в одном каталоге. Я не знаком с ext4 конкретно, но для других форматов записи каталога были просто помечены как неиспользуемые при удалении файлов. Это означает, что они все равно должны быть пропущены при выполнении операций в каталоге. Это объясняет поведение, которое вы видите.
KeithB
1
Я удалил «теперь более медленный» каталог и использовал другое имя для нового каталога. Время создания 1 миллиона файлов теперь сократилось до 1 м 33 с (против 9 м 30 с, когда каталог «содержит» 2 млн удаленных файлов, первый миллион с тем же именем, что и вновь добавленный 1 млн) ... интересно, и это подсчитывает ваш "... только что отмеченный как неиспользованный" комментарий ... как добраться; это начинает иметь смысл :)
Peter.O
@ fred.bear Мой плохой, я действительно не знал реальной иерархии, и мой ответ был угадать. Кроме того, ваш тест на самом деле подчеркивает метаданные, но не фактические файлы, поскольку они являются пустыми файлами. Лучший способ сравнить этот тип проблемы - это взять файлы из / var или кеша веб-сервера. В любом случае, ваш тест тоже звучит интересно, вы можете попробовать удалить его двумя указанными методами в разных каталогах, например, /sample1/1.txt,2.txt ... и /sample2/1.txt,2.txt ..
rajaganesh87
@ Mr.Confused.A.Lot ... Спасибо за помощь. Ваше объяснение помогло мне лучше понять файловую систему и некоторые ее особенности ... Теперь у меня есть разумное представление о причинах различных проблем со скоростью ... некоторые из них были просто выбором команд bash, а другие - просто проблемами файловой системы ( У меня остался новый девиз: «большое - это плохо» для каталогов ... (по крайней мере, для некоторых действий) ...
Peter.O
2

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

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

Конечно, все это небрежно заимствует понятия из хеш-таблиц.

sehe
источник
Я думаю, что вы говорите «используйте меньшие каталоги» ... Это интересная идея; самодельная СУБД, которая создает дерево из группы файлов «без деревьев». Некоторые могут назвать это перспективным планированием :) ... Если это работает (и, вероятно, работает), то это хорошая идея ! :) ... Я начинаю понимать, что "большой - это плохо", когда дело доходит до количества файлов в каталоге (по крайней мере, для ext4) ... Вы представили упреждающий обходной путь (+1), и я '
Я медленно понимаю,
Да, извините за то, что не был более ясным в идее держать dirs маленьким
sehe