Чому видалення файлів на ім’я болісно повільне, а також надзвичайно швидке?


11

Faux pas: "Швидкий" метод, про який я згадую нижче, не в 60 разів швидший, ніж повільний. Це в 30 разів швидше. Я буду звинувачувати помилку в годину (3:00 - це не найкращий час дня для чіткого мислення :) ..

Оновлення: я додав підсумок тестових разів (нижче).
Здається, що з коефіцієнтом швидкості є два питання:

  • Вибір використовуваної команди (Порівняння часу показано нижче)
  • Характер великої кількості файлів у каталозі ... Здається, що "великий - це погано". Речі стають непропорційно повільнішими, оскільки кількість збільшується.

Усі тести виконані з 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цикл.
Файл подачі є результатом ls -1 -f
Методи однакові у всіх повторах, за винятком одного:

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

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

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

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

BTW: Видалення файлів через "відсортований список" імен насправді швидше, ніж rm -rfв 2 рази,
і: rm -rбуло в 30 разів повільніше, ніж метод "відсортований список"

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

Що мене дуже спантеличує, це те, що кожен дзвінок не rm filenameмає відношення до попереднього .. (ну, принаймні, саме так з точки зору "баш")

Я використовую привід Ubuntu / bash / 'ext4' / SATA II.


1
Ти робиш це неправильно! (тм) Коли-небудь чули find -delete?
alex

Ваші 2 тести починаються в нерівних умовах (я не вважаю, що це дійсно важливо): один зчитує назви файлів з файлу, а другий читає назви файлів з файлу, який був створений (відсортований) безпосередньо перед тестом. Можливо, файл, який кешується у другому випадку, відтворює певний (а може і ні, хто знає). Щоб тести були в більш рівних умовах, можливо, вам слід зробити простий catу свіжому файлі до першого тесту - замість sortдо 2-го тесту.
imz - Іван Захарящев

І я рекомендую вам представити свої спостереження та своє питання більш чітко. Будь ласка, одна справа за один раз: порівняйте лише два випадки в одному питанні, винесіть два важливих справи на передній план, всі інші - лише довідкова інформація; будь ласка, поясніть це. Не змішуйте декілька спостережень в одній публікації, будь ласка.
imz - Іван Захарящев

Представлення системного та простору часу для користувачів також може бути важливим для вирішення головоломки, тому, будь ласка, включіть їх у своє запитання. Який із них має велике значення у ваших тестах?
imz - Іван Захарящев

1
Передчасна оптимізація - корінь усього зла. :) Коли ви коли-небудь видалите 10 мільйонів файлів? 100 000 в секунду мені здаються досить швидкими (щоб зруйнувати вашу систему).
користувач невідомий

Відповіді:


2

Очікується, що rm -r буде повільним, оскільки його рекурсивний. Перший обхід по глибині має бути зроблений у структурі каталогу.

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

"ls -f" дозволить -aU, який перераховується в порядку каталогу, який знову рекурсивний.


1
МакАлот: Я не бачу, як «рекурсивний» матиме значення в цьому випадку , оскільки тут немає ніяких підкаталогів ... Так, я використовував "1.txt, 2.txt, 3.txt". Можливо, є кілька речі, що взаємодіють: наприклад, для створення 1 мільйона файлів потрібно лише 1 хв 30-х, але для створення 2 млн. потрібні 7 м 10 секунд, а після їх видалення відтворення 1 мільйона значно довше (9 м 30-х років) дивно; все працює повільно раптом. Це сталося і раніше. Я думаю, що (?) видалення каталогу виправило це. Чи може бути задіяний демон-файл (nautilus; знайти), можливо? Продовження ...
Peter.O

Взагалі файлові системи не оптимізовані для роботи з великою кількістю файлів в одному каталозі. Я конкретно не знайомий з ext4, але для інших форматів записи каталогів були просто позначені як невикористані при видаленні файлів. Це означає, що їх все одно потрібно пропускати, виконуючи операції в каталозі. Це пояснило б поведінку, яку ви бачите.
KeithB

1
Я видалив каталог "зараз повільніше" і використав іншу назву для нового каталогу. Час створення 1 мільйона файлів тепер повертається до 1м 33с (проти 9м 30-х, коли каталог "містить" 2 мільйони видалених файлів, перший мільйон має те саме ім'я, як щойно доданий 1 мільйон) ... цікаво, і це балачки з вашим "... щойно позначеним як невикористаним" коментарем ... потрапляння туди; це починає мати сенс :)
Пітер.О

@ 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

робити щось розумніше, як (припускає Баш):

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

Звичайно, це все неохайно запозичення понять із хештелів


Я думаю, що ви говорите "використовувати менші каталоги" ... Це заперечна ідея; домашня СУБД, яка робить дерево із групи файлів "без дерева". Дехто може назвати це планування вперед :) ... Якщо це працює (і це, мабуть, так), то це гарна ідея ! :) ... Я починаю уявляти, що "великий - це погано", якщо мова йде про кількість файлів у каталозі (як мінімум для ext4) ... Ви подали попереджувальне вирішення (+1), і я " м. повільно отримую уявлення про те, чому деякі методи видалення швидші, ніж інші, в будь-якому даному каталозі; малі або великі ... Дякую
Peter.O

Вибачте за те, що ви не стали більш
чіткими
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.