Самый быстрый способ удалить много файлов

Перенос из темы «Разговоры о компьютерах»
 

stas27

эксперт
★★☆
Mishka>> А простенькая программка на С или С++ (можно и python/perl попробовать) будет не быстрее?
TbMA> Про остальные не скажу, а перлом пробовали. Намного медленнее выходит.

Медленнее, чем что? rsync?
С уважением, Стас.  29.0.1547.7629.0.1547.76
+
+1
-
edit
 

TbMA

опытный

stas27> Медленнее, чем что? rsync?

Да, чем rsync. rsync еще хорош тем, что он железно заканчивает начатое (сколько бы это ни заняло).
 23.023.0

stas27

эксперт
★★☆
stas27>> Медленнее, чем что? rsync?
TbMA> Да, чем rsync. rsync еще хорош тем, что он железно заканчивает начатое (сколько бы это ни заняло).

Ok, спасибо. Может, и мне как-нибудь пригодится :)
С уважением, Стас.  

Floyd

аксакал

Floyd>> Так что же они там читают ?
Mishka> А ты подумай

Так что же об утилизации памяти.
Не спроста это утверждение пончалу поставило меня в тупик


Вот результаты тестов с HP-UX 11.31 PA


touch {1..100000} - в виду ограничения на длину аргумента
code text
  1.                          User      CPU %    Thrd Disk        Memory       Block
  2. Process Name     PID     Name   ( 400% max) Cnt  IOrate      RSS/VSS      On
  3. --------------------------------------------------------------------------------
  4. touch               8960 root         99.8     1   6.0     2.3mb    2.3mb   PRI


rm * для 100000 файлов

code text
  1.                          User      CPU %    Thrd Disk        Memory       Block
  2. Process Name     PID     Name   ( 400% max) Cnt  IOrate      RSS/VSS      On
  3. --------------------------------------------------------------------------------
  4. rm                  6940 root         64.7     1 230.4     2.2mb    2.2mb  died

2.2 mb против 20 на линуксе




find -exec rm -f
code text
  1.                          User      CPU %    Thrd Disk        Memory       Block
  2. Process Name     PID     Name   ( 400% max) Cnt  IOrate      RSS/VSS      On
  3. --------------------------------------------------------------------------------
  4. find                9658 root         39.4     1   8.8     2.3mb    2.3mb SLEEP

Опять же 2.2 против 20 на линуксе


rm -rf /tmp/22222/ для 100000 файлов
code text
  1.                         User      CPU %    Thrd Disk        Memory       Block
  2. Process Name     PID     Name   ( 400% max) Cnt  IOrate      RSS/VSS      On
  3. --------------------------------------------------------------------------------
  4. rm                 13151 root         47.2     1 387.7     292kb    356kb    IO

356kb против 20mb на линуксе


rm -rf /tmp/22222/ на 700000 файлов

code text
  1.                          User      CPU %    Thrd Disk        Memory       Block
  2. Process Name     PID     Name   ( 400% max) Cnt  IOrate      RSS/VSS      On
  3. --------------------------------------------------------------------------------
  4. rm                 18101 root         63.4     1 427.5     292kb    356kb   PRI



356kb против 150mb на линуксе


WTF?

Чпукс выполняет последовательность lstat/sysfs/unlink после каждой порции структур полученных getdents

code text
  1. getdents(6, 0x40007790, 8192) ......................................................................................................... = 3960
  2. lstat64("340", 0x77ff1268) ............................................................................................................ = 0
  3. sysfs(GETFSIND, 0x400017a0, 0x77ff1268) ............................................................................................... = 7
  4. unlink("340") ......................................................................................................................... = 0
  5. lstat64("341", 0x77ff1268) ............................................................................................................ = 0
  6. sysfs(GETFSIND, 0x400017a0, 0x77ff1268) ............................................................................................... = 7
  7. unlink("341") ......................................................................................................................... = 0
  8. lstat64("342", 0x77ff1268) .............


В то время как Linux формирует массив дескрипторов и залпом делает unlink для всех

Что лучше, что хуже однозначно судить не возьмусь - резмен скорости на память.




И еще одна статейка по теме

You can list a directory containing 8 million files! But not with ls.. | Something People Want

I needed to list all files in a directory, but ls, find, and os.listdir all hung. This is my story. NOTE: there is no good reason that you should ever have 8 million files in the same directory, but if you do, this is your solution . TLDR: Write a C program that calls the... // www.olark.com
 
 29.0.1547.7629.0.1547.76

Mishka

модератор
★★★
TbMA> Про остальные не скажу, а перлом пробовали. Намного медленнее выходит.
Ну, я свою программульку чуть развил и дополнил регулярными выражениями, чтобы можно было из 20 лимонов только 6 лимонов удалить. :F Пришлось только вызывать так, чтобы параметры были без substitute шеллом, а сразу шли в программульку, а та уже применяла бы RE к прочитанному DIR. :F Бегала весьма шустро.
 17.017.0

Mishka

модератор
★★★
Floyd> Потому же почему и нельзя сделать rm *, argument to long ;)
Дык, памяти-то не хватает почему? Потому, что шелл (как правило) старается сделать полный substitute звезды, а потом сразу всё и потереть разом. Аналогично, при обходе дерева, можно обходить слева или справа, а можно по уровням. Затраты ненмого разные. А можно все текущие файлы прочитать скопом, а потом вторым проходом удалить. Вот в таком случае при большом количестве файлов наступает попа. Аналогично с поддиректориями — если их запоминать, для того, чтобы обработать позже, то наступает такая же попа. Поэтому я и написал в программке так, что два прохода (и без fstat-а — у меня по условию были или директории, или файлы, или мягкие ссылки). Сначала по одному удаляем файлы, потом перематываем директорию вначало и продолжаем обход дерева начиная с первой структуры (остались одни поддиректории). Поэтому и рекурсивно сделал, бо длина пути сильно ограничена и эта же длина ограничивает уровень вложения директорий.
 17.017.0

Mishka

модератор
★★★
У HP-UX почти весь код сидит в shared library, поэтому основные бинарники очень часто маленькие. Зато, если незадачливый админ снесёт такую библиотечку, то начинается такое... жа

Floyd> В то время как Linux формирует массив дескрипторов и залпом делает unlink для всех

Массив имён? unlink принимает строку, а не дескриптор.

Floyd> Что лучше, что хуже однозначно судить не возьмусь - резмен скорости на память.


У меня readdir вполне нормально сработал. 32k входов за раз — это много. На миллион входов всего ~34 чтения. На 8 лимонов ~272 чтения.
 17.017.0

Floyd

аксакал

Mishka> У HP-UX почти весь код сидит в shared library, поэтому основные бинарники очень часто маленькие. Зато, если незадачливый админ снесёт такую библиотечку, то начинается такое... жа

Оно может и так, но в данном случае (речь идет потреблении памяти команой rm -rf) дело именно в алгоритме работы. Чпукс читает содержимое директирии блоками по 8кб, обрабатывает, затем читает новую порцию.

Floyd>> В то время как Linux формирует массив дескрипторов и залпом делает unlink для всех
Mishka> Массив имён? unlink принимает строку, а не дескриптор.

Да, массив имен.
 

Floyd

аксакал

В общем это я все к тому что утверждение ТЬМЫ

TbMA> Не в этом дело, а в том что они читают в память, и если памяти не тонны (а на живой машине ее обычно не тонны) то быстро вылетают в свап. И начинаются дикие тормоза.

Есть частный случай характерный для Linux
 

Floyd

аксакал

Floyd>> Потому же почему и нельзя сделать rm *, argument to long ;)
Mishka> Дык, памяти-то не хватает почему? Потому, что шелл (как правило) старается сделать полный substitute звезды, а потом сразу всё и потереть разом.

Тут как раз все было ясно, меня удивил тот факт что при выполнении rm -rf на директорию с 700 000 файлов он сожрал 150 метров оп.
 

Mishka

модератор
★★★
Floyd> Тут как раз все было ясно, меня удивил тот факт что при выполнении rm -rf на директорию с 700 000 файлов он сожрал 150 метров оп.
Дык, нет команды системного вызова (из С-либа), который удалит сразу и директорию, и файлы. Значит нужно пробежаться по поддиректории, выудить все поддиректории, все файлы, а потом удалять файлы и повторять по поддиректориям. Вот и выходит, что в памяти хранить надо. :) Если только не писать обход по особому.
 24.024.0

Floyd

аксакал

Mishka>Значит нужно пробежаться по поддиректории, выудить все поддиректории, все файлы, а потом удалять файлы и повторять по поддиректориям. Вот и выходит, что в памяти хранить надо. :) Если только не писать обход по особому.

Но, позвольте, почему же тогда динозавр HP-UX не строит один большой массив, а обрабатывает по 8Кб после каждого вызова getdents!?
 24.024.0
+
+1
-
edit
 

Mishka

модератор
★★★
Floyd> Но, позвольте, почему же тогда динозавр HP-UX не строит один большой массив, а обрабатывает по 8Кб после каждого вызова getdents!?
Чпуксеры всегда отличались тем, что не использовали интерфейс, который предлагали пользователям. Я работал с 9-й, 10-й, 11-й в 1996-1999 годах, когда мы перелезли с Dynix/ptx от Sequent-а (и железо "обновили" — в кавычках, т.к. наша машинка 8 летней давности на 8 486-х процах приделывала наши все К системы, а потом и V систему на 32 процах, но Sequent умирала уже как компания). Они напрямую пользовались вызовами кернела. Ну и обходы дерева могут быть разными — левый-правый и по уровням два самых известных из учебников. Вопрос что вначале обрабатывать — местные значения или значения из подузлов — вопрос часто идиологический, т.к. в сортированных случаях, где иногда надо вставлять, приходится иметь всякие минмаксы для текущего узла и работать в их пределах. Поэтому иногда такую идеологию переносят на неупорядоченные деревья, хотя это там и не надо. Тем более, что почти всегда в FS не двоичные деревья (binary trees), а просто B-trees. Тот же inode типичный представитель блока.
 24.024.0
01.10.2013 19:24, Floyd: +1: Твой опыт всегда интересен

Floyd

аксакал

Mishka>

Жалко трейсы не сохранил, но поверь на слово что Linux выполняет все те же getdents только блоками по 32кб для всей директории разом. Ок, по поводу алгоритмических особенностей возразить нечего, но ИМХО все корни тянутся из того времени когда никто не предполагал использование Linux в более или менее серьезном секторе.
 24.024.0

Mishka

модератор
★★★
Floyd> Жалко трейсы не сохранил, но поверь на слово что Linux выполняет все те же getdents только блоками по 32кб для всей директории разом.

Обломками по 32Кб — это следствие применения C библиотеки. :F Это readdir так читает. И про это в одной из ссылок прямо написано (из тех, что выше давали). И сетовали, что очень медленно получается. Т.е. в конечном итоге, конечно же, всё сводится к системному вызову. Но править на лине всякие изменения кернела проще — в библиотеке поправил и всё, что пользуется библиотекой, сразу работает. А Чпуксе бывали и ошибки, когда правили, но как-то криво, бо править надо было в всех командах из /bin и /sys/bin.

Floyd> Ок, по поводу алгоритмических особенностей возразить нечего, но ИМХО все корни тянутся из того времени когда никто не предполагал использование Linux в более или менее серьезном секторе.
Вполне возможно.
 24.024.0
+
+1
-
edit
 

Balancer

администратор
★★★★★
stas27> По совету Гугля?

Ссылка уже не живая, зато тут есть с оценками скорости разных методов:

Which is the fastest method to delete files in Linux

How to delete large number of files in linux. Comparison of different methods used for file deletion in linux to find the faster method for a million files. // www.slashroot.in
 
 4141
RU спокойный тип #20.04.2015 09:41  @Balancer#27.03.2015 16:29
+
-
edit
 

спокойный тип
Спокойный_Тип

старожил
★☆
кстати у меня на прошлой неделе была похожая задачка, на ext3 в папке кэша mod_proxy была хренова туча файлов...быстрее всего зачистилось банальной

nohup rm -rf .... &

c ренайсом под -1

она подкачивает ограниченный список файлов, стирает , потом по новой
 37.037.0
IL digger #21.04.2015 17:20  @спокойный тип#20.04.2015 09:41
+
-
edit
 

digger

аксакал

Мне кажется,самое быстрое - создать список файлов,а потом удалять по имени каждый в отдельности.Технически findfirst/findnext просто читает директорию,ничего не удаляя и не обновляя,это самый быстрый способ перечислить файлы,а удалять по одному и больше ничего - опять самый быстрый способ это сделать.
 37.037.0

Mishka

модератор
★★★
digger> Мне кажется,самое быстрое - создать список файлов,а потом удалять по имени каждый в отдельности.Технически findfirst/findnext просто читает директорию,ничего не удаляя и не обновляя,это самый быстрый способ перечислить файлы,а удалять по одному и больше ничего - опять самый быстрый способ это сделать.

Не, на каждый запрос удалить одиночный файл происходит полноценный поиск его в директории, которая может быть распределена по диску. Да ещё, если блок освободится первый, придётся делать работу по выплетению из структуры. А всякие там findfirts/findnext (Windows — на Лине чуток по другому называется), октрывают один раз и шуруют до конца. Может быть переплетение, но поиск не происходит точно каждый раз.
 37.037.0

digger

аксакал

Да,readdir возвращает inode,по которому можно удалять,a FindFirstFile не возвращает ничего,кроме имени.Используя это,можно написать утилиту для быстрого удаления,или rm уже это использует.
 37.037.0
Последние действия над темой

в начало страницы | новое
 
Поиск
Настройки
Твиттер сайта
Статистика
Рейтинг@Mail.ru