Ускорить перечисление файлов NTFS (используя журнал FSCTL_ENUM_USN_DATA и NTFS MFT / USN)
Я перечисляю файлы, просматривая журнал NTFS MFT / USN с:
HANDLE hDrive = CreateFile(szVolumePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);
DWORD cb = 0;
MFT_ENUM_DATA med = { 0 };
med.StartFileReferenceNumber = 0;
med.LowUsn = 0;
med.HighUsn = MAXLONGLONG; // no change in perf if I use med.HighUsn = ujd.NextUsn; where "USN_JOURNAL_DATA ujd" is loaded before
unsigned char pData[sizeof(DWORDLONG) + 0x10000] = { 0 }; // 64 kB
while (DeviceIoControl(hDrive, FSCTL_ENUM_USN_DATA, &med, sizeof(med), pData, sizeof(pData), &cb, NULL))
{
med.StartFileReferenceNumber = *((DWORDLONG*) pData); // pData contains FRN for next FSCTL_ENUM_USN_DATA
// here normaly we should do: PUSN_RECORD pRecord = (PUSN_RECORD) (pData + sizeof(DWORDLONG));
// and a second loop to extract the actual filenames
// but I removed this because the real performance bottleneck
// is DeviceIoControl(m_hDrive, FSCTL_ENUM_USN_DATA, ...)
}
Работает, намного быстрее чем обычно FindFirstFile
методы перечисления. Но я вижу, что это еще не оптимально:
На моих файлах 700k
C:\
, это занимает 21 сек. (Эта мера должна быть выполнена после перезагрузки, в противном случае она будет неправильной из-за кэширования).Я видел другое программное обеспечение для индексирования (не все, другое), способное индексировать
C:\
в течение < 5 секунд (измеряется после запуска Windows), без чтения предварительно рассчитанной базы данных в файле.db (или других подобных приемов, которые могут ускорить процесс!). Это программное обеспечение не используетFSCTL_ENUM_USN_DATA
, но анализ NTFS низкого уровня вместо.
Что я пытался улучшить производительность:
Открыть файл с другим флагом, например
FILE_FLAG_SEQUENTIAL_SCAN
,FILE_FLAG_RANDOM_ACCESS
, или жеFILE_FLAG_NO_BUFFERING
: тот же результат: 21 секунда на чтениеРассматривая оценку количества записей USN на томе NTFS, почему перечисление файлов с помощью DeviceIoControl выполняется быстрее в VB.NET, чем в C++? Я изучил их подробно, но это не дает ответа на этот актуальный вопрос.
Протестируйте другой компилятор: MinGW64 вместо VC++ Express 2013: тот же результат производительности, без разницы
На VC++ я уже перешел на
Release
вместоDebug
: есть ли другие свойства проекта / опции, которые могли бы ускорить программу?
Вопрос:
Можно ли улучшить производительность DeviceIoControl(hDrive, FSCTL_ENUM_USN_DATA, ...)
?
или это единственный способ повысить производительность, выполнив низкоуровневый ручной анализ NTFS?
Примечание: согласно тестам, общий размер для чтения во время этих DeviceIoControl(hDrive, FSCTL_ENUM_USN_DATA, ...)
для моих 700к файлов всего 84MB. 21 секунда для чтения 84 МБ - это всего 4 МБ / с (и у меня есть SSD!). Возможно, есть место для улучшения производительности, не правда ли?