Я перечисляю файлы, просматривая журнал 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, ...)
для моих 700k файлов только 84MB. 21 секунда для чтения 84 МБ — это всего 4 МБ / с (и у меня есть SSD!). Возможно, есть место для улучшения производительности, не правда ли?
Задача ещё не решена.
Других решений пока нет …