Подтвердить что ты не робот

Как я могу быстро перечислить каталоги на Win32?

Я пытаюсь ускорить перечисление каталога в С++, где я возвращаюсь в подкаталоги. В настоящее время у меня есть приложение, которое тратит 95% своего времени в API FindFirst/FindNextFile, и для перечисления всех файлов на данном томе требуется несколько минут. Я знаю, что это можно сделать быстрее, потому что есть приложение, которое делает: Все. Он перечисляет весь мой диск за считанные секунды.

Как я могу выполнить что-то вроде этого?

4b9b3361

Ответ 1

Я понимаю, что это старый пост, но есть проект в исходной кузнице, который делает именно то, что вы просите, и исходный код доступен.

Вы можете найти проект здесь: NTFS-Search

Ответ 2

"Все" обращается к информации каталога на более низком уровне, чем API Win32 FindFirst/FindNext.

Я считаю, что он читает и интерпретирует структуры NTFS MFT напрямую и что это одна из основных причин его производительности. Это также объясняет, почему для этого требуются привилегии администратора и почему "все" индексирует только локальные или удаленные тома NTFS (например, не сетевые диски).

Пара других утилит, которые делают подобные вещи:

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

Ответ 3

"Все" строит индекс в фоновом режиме, поэтому запросы против индекса не являются самой файловой системой.

Существует несколько улучшений - по крайней мере, по прямому алгоритму:

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

В Windows 7/W2K8R2 вы можете использовать FindFirstFileEx с FindExInfoBasic, при этом основное ускорение пропускает короткое имя файла в файловых системах NTFS, где это разрешено.

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


[edit] Wikipedia на самом деле есть некоторые комментарии - В основном, они пропускают слой абстракции файловой системы и напрямую обращаются к NTFS. Таким образом, они могут выполнять пакетные вызовы и пропускать дорогостоящие службы файловой системы - например, проверять ACL.

Хорошей отправной точкой будет Техническая ссылка NTFS на MSDN.

Ответ 4

Если вы делаете это на NTFS, здесь lib для доступа с низким уровнем доступа: NTFSLib.

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

Это может быть самый быстрый способ перечислить все файлы/каталоги на томах NTFS, файлы 200 тыс. ~ 300 тыс. в минуту, как я тестировал.

Ответ 5

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

Ответ 6

Если вы уже делаете все возможное, чтобы получить максимальную скорость от API, следующим шагом будет сделать низкоуровневые обращения к диску и обойти Windows в целом. Вы можете получить руководство от NTFS-драйверов для Linux или, возможно, вы можете использовать его напрямую.