Как быстро удалить миллионы файлов
мы используем 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 + - дерева, т. е. сортировать их в алфавитном или индексе, а затем сделать один из:
- отсоединить от первой записи, идущей вперед.
- отсоединить от последней записи, идущей назад.
- отсоединить от первой записи, затем последней записи, двигаясь к центру.
Я бы сравнил все шесть подходов для ваша конкретная система регистрации, и выбрать тот, который является самым быстрым. Некоторые используют Б+ деревья по номеру inode, некоторые основаны на leafname, она колеблется. Но в основном вы хотите избежать чрезмерного перебалансировки дерева и избежать глубокого поиска o(log N) имени листа, поэтому упорядоченные ссылки.
Если вы хотите освободить требуемое место, самый быстрый способ сделать это-переместить (или переименовать) каталог в другое место на том же разделе. Затем ваша программа может продолжить работу с требуемым местоположением и удалить ранее перемещенный каталог рекурсивно в другом потоке (в фоновом режиме). Этот поток может работать даже с меньшим приоритетом, поэтому удаление определенного каталога будет выглядеть как мгновенная операция файловой системы.
статья, на которую вы ссылаетесь, рассказывает о перспективе оболочки. Это критически важно: оболочка запускает программы для многих задач. И хотя запуск программы очень дешев, он может быть дорогим, когда вам нужно запустить миллион программ. Вот почему rsync
настолько эффективно; один вызов может сделать всю работу.
то же самое относится к вашей программе. Вы запускаете свою программу один раз; стоимость-это просто все syscalls, которые вы делаете.
Я проверил список syscall; нет syscall, который позволяет выполнять массовое удаление с одним syscall, поэтому вы ограничены одним syscall на файл для удаления.
в зависимости от архитектуры хранилища, вы можете получить ускорение, удаляя файлы параллельно. Итак, разделите работу между std::thread
s, или если вы хотите попробовать очень быстро, используйте прагму OpenMP.
вот как я управляю своими ящиками хранения ~ 200 Тб.
обратите внимание, что можно иметь небольшое состояние гонки, если какой-либо из файлов связан друг с другом, но пока вы обрабатываете ошибку, это должно быть хорошо.