Как быстро удалить миллионы файлов

мы используем BOOST1.63 boost::filesystem::remove_all(dir_to_remove) чтобы удалить папку с миллионами файлов (каждый файл имеет размер 1 МБ). Папка "dir_to_remove" имеет подпапки, и каждая подпапка имеет не более 1000 файлов. Удаление всех файлов занимает более 10 минут. Мы используем CentOS6.5.

после проверки операции.cpp, мы поняли, что BOOST фактически использует Linux rmdir и unlink команды:

#   define BOOST_REMOVE_DIRECTORY(P)(::rmdir(P)== 0)
#   define BOOST_DELETE_FILE(P)(::unlink(P)== 0)

этой статьи перечислены несколько способов удаления файлов больше эффективно на Linux. И рекомендуется использовать rsync.

как мы можем быстро удалить миллионы файлов с помощью C++?

4 ответов


да, std::filesystem::directory_iterator довольно скучно. Я ищу, чтобы заменить этот объект полностью в предстоящем P1031 низкий уровень ввода/вывода (примечание не будет жить на WG21 до июня 2018 года) с чем-то, что хорошо масштабируется для ввода, поэтому мы на нем.

тем временем, я бы предложил вам использовать https://ned14.github.io/afio/ который является эталонной реализацией для P1031, в частности directory_handle::enumerate(). Эта библиотека обрабатывает каталоги с миллионами, даже десятками из миллионов файлов с легкостью. После того, как у вас есть список записей для удаления, вам нужно следовать шаблону удаления B + - дерева, т. е. сортировать их в алфавитном или индексе, а затем сделать один из:

  1. отсоединить от первой записи, идущей вперед.
  2. отсоединить от последней записи, идущей назад.
  3. отсоединить от первой записи, затем последней записи, двигаясь к центру.

Я бы сравнил все шесть подходов для ваша конкретная система регистрации, и выбрать тот, который является самым быстрым. Некоторые используют Б+ деревья по номеру inode, некоторые основаны на leafname, она колеблется. Но в основном вы хотите избежать чрезмерного перебалансировки дерева и избежать глубокого поиска o(log N) имени листа, поэтому упорядоченные ссылки.


Если вы хотите освободить требуемое место, самый быстрый способ сделать это-переместить (или переименовать) каталог в другое место на том же разделе. Затем ваша программа может продолжить работу с требуемым местоположением и удалить ранее перемещенный каталог рекурсивно в другом потоке (в фоновом режиме). Этот поток может работать даже с меньшим приоритетом, поэтому удаление определенного каталога будет выглядеть как мгновенная операция файловой системы.


статья, на которую вы ссылаетесь, рассказывает о перспективе оболочки. Это критически важно: оболочка запускает программы для многих задач. И хотя запуск программы очень дешев, он может быть дорогим, когда вам нужно запустить миллион программ. Вот почему rsync настолько эффективно; один вызов может сделать всю работу.

то же самое относится к вашей программе. Вы запускаете свою программу один раз; стоимость-это просто все syscalls, которые вы делаете.

Я проверил список syscall; нет syscall, который позволяет выполнять массовое удаление с одним syscall, поэтому вы ограничены одним syscall на файл для удаления.


в зависимости от архитектуры хранилища, вы можете получить ускорение, удаляя файлы параллельно. Итак, разделите работу между std::threads, или если вы хотите попробовать очень быстро, используйте прагму OpenMP.

вот как я управляю своими ящиками хранения ~ 200 Тб.

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