Открытие большого количества маленьких файлов в NTFS слишком медленно

Я пишу программу, которая должна обрабатывать много маленьких файлов, скажем, тысячи или даже миллионы.
Я тестировал эту часть на файлах размером 500 тыс., И первым шагом было просто выполнить итерацию каталога, содержащего около 45 тыс. Каталогов (включая подкаталоги подкаталогов и т. Д.) И 500 тыс. Небольших файлов. Обход всех каталогов и файлов, включая получение размеров файлов и вычисление общего размера, занимает около 6 секунд. Теперь, если я попытаюсь открыть каждый файл во время обхода и сразу же закрыть его, похоже, он никогда не останавливается. На самом деле, это занимает слишком много времени (часы …). Так как я делаю это в Windows, я попытался открыть файлы с помощью CreateFileW, _wfopen и _wopen. Я ничего не читал и не записывал в файлы, хотя в финальной реализации мне нужно будет только читать. Однако я не увидел заметного улучшения ни в одной из попыток.

Интересно, есть ли более эффективный способ открывать файлы с помощью любой из доступных функций, будь то C, C ++ или Windows API, или единственным более эффективным способом будет чтение MFT и чтение блоков диска напрямую, которое я пытаюсь избежать?

Обновление: приложение, над которым я работаю, делает резервные снимки с контролем версий. Таким образом, он также имеет дополнительные резервные копии. Тест с 500k-файлами выполняется в огромном хранилище исходного кода для создания версий, что-то вроде scm. Итак, все файлы не находятся в одном каталоге. Есть также около 45 тысяч каталогов (упомянутых выше).

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

6

Решение

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

Любой файл размером более 1000 байтов является «большим» для NTFS. Если бы был способ сделать большинство файлов данных менее чем около 900 байтов, Вы можете реализовать большую эффективность, храня данные файла в MFT. Тогда получить данные будет не дороже, чем получить временные метки или размер файла.

Я сомневаюсь, что есть какой-либо способ оптимизировать параметры программы, параметры процесса или даже параметры настройки операционной системы, чтобы приложение работало хорошо. Вы сталкиваетесь с многочасовой работой, если вы не можете перестроить ее радикальным образом.

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

Другой стратегией может быть реорганизация всех файлов в несколько больших файлов, таких как большие файлы .zip, как предложено @felicepollano, для эффективной виртуализации вашего набора файлов. Произвольный доступ к файлу размером 4000 ГБ по своей природе является гораздо более эффективным и действенным использованием ресурсов, чем доступ к файлам объемом 4 миллиарда 1 МБ. Кроме того, перемещение всех данных в подходящий менеджер баз данных (MySQL, SQL Server и т. Д.) Позволит добиться этого и, возможно, даст другие преимущества, такие как простой поиск и простая стратегия архивирования.

6

Другие решения

Затраты от 5 до 20 мс на файл не являются необычными для тома NTFS с таким количеством файлов. (В любом случае на обычном дисковом шпинделе вы не можете ожидать гораздо большего, потому что он находится в том же порядке, что и время поиска головок. С этого момента, я предполагаю, что мы имеем дело с оборудованием корпоративного класса, SSD и / или RAID.)

Исходя из моего опыта, вы можете значительно увеличить пропускную способность, распараллеливая запросы, то есть используя несколько потоков и / или процессов. Кажется, что большая часть накладных расходов приходится на каждый поток, система может открывать сразу десять файлов почти так же быстро, как она сама может открыть один файл. Я не уверен, почему это так. Возможно, вам придется поэкспериментировать, чтобы найти оптимальный уровень распараллеливания.

Системный администратор также может значительно повысить производительность, скопировав содержимое на новый том, предпочтительно примерно в том же порядке, в котором они будут доступны. Мне пришлось сделать это недавно, и это сократило время резервного копирования (для тома с около 14 миллионами файлов) с 85 до 18 часов.

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

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

3

Есть способ взломать, который вы можете попробовать: заархивировать эти файлы с низкой степенью сжатия, а затем использовать некоторые библиотеки Zip для их чтения, это обычно намного быстрее, чем чтение отдельных файлов один за другим.
Конечно, это должно быть сделано заранее как предварительный этап процесса.

1

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

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

Также проверьте наличие антивирусных программ в вашей системе. Некоторые замедляют каждый доступ к файлу, сканируя весь файл каждый раз, когда вы пытаетесь получить к нему доступ. Использование Sysinternals Procmon поможет вам определить проблему такого рода.

Когда вы пытаетесь улучшить производительность, стоит поставить перед собой цель. Как быстро достаточно быстро?

РЕДАКТИРОВАТЬ: Эта часть исходного ответа не применяется, если вы не используете Windows XP или более раннюю версию:

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

1

NTFS работает медленно с большим количеством файлов. Особенно, если они находятся в одном каталоге. Когда они разделены на отдельные каталоги и подкаталоги, доступ становится быстрее. У меня есть опыт работы со многими файлами, хранящимися на плате видеокамеры (4 камеры), и она была слишком медленной, чтобы увидеть количество файлов и их размер (Свойства корневой папки). Интересно, что когда диск FAT32, то же происходит гораздо быстрее. И все источники говорят, что NTFS быстрее … Может быть, быстрее для чтения одного файла, но операции с каталогами медленнее.

Зачем вам так много файлов? Я надеюсь, что служба индексирования каталогов включена.

1
По вопросам рекламы [email protected]