самый быстрый способ проверить рекурсивные ntfs каталоги в C++

Я записал маленький поисковый робот, чтобы просканировать и обратиться структуры каталогов.

Это на основе dirent (который является маленькой оберткой вокруг FindNextFileA) В моих первых сравнительных тестах это - медленный surprisingy:

приблизительно 123 473 мс для 4 500 файлов (thinkpad t60p локальный Samsung 320 ГБ 2,5 дюйма HD). 121 481 файл, найденный в 123 473 миллисекундах, Является этой нормальной скоростью?

Это - мой код:

int testPrintDir(std::string  strDir, std::string strPattern="*", bool recurse=true){
  struct dirent *ent;
  DIR *dir;
  dir = opendir (strDir.c_str());
  int retVal = 0;
  if (dir != NULL) {
    while ((ent = readdir (dir)) != NULL) {
      if (strcmp(ent->d_name, ".") !=0 &&  strcmp(ent->d_name, "..") !=0){
        std::string strFullName = strDir +"\\"+std::string(ent->d_name);
        std::string strType = "N/A";
        bool isDir = (ent->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) !=0;
        strType = (isDir)?"DIR":"FILE";                 
        if ((!isDir)){
             //printf ("%s <%s>\n", strFullName.c_str(),strType.c_str());//ent->d_name);
          retVal++;
        }   
        if (isDir && recurse){
             retVal += testPrintDir(strFullName, strPattern, recurse);
        }
      }
    }
    closedir (dir);
    return retVal;
  } else {
    /* could not open directory */
    perror ("DIR NOT FOUND!");
    return -1;
  }
}
6
задан Peter Parker 14 June 2010 в 22:11
поделиться

4 ответа

В некоторых случаях такая скорость является нормальной, да. Во-первых, использование FindFirstFileA вместо FindFirstFileW приведет к накладным расходам при преобразовании из UTF-16 в ANSI. Во-вторых, если вы просматриваете каталоги, к которым еще не обращалась операционная система, вы понесете по крайней мере один штраф за поиск (около 16 мс для большинства потребительских жестких дисков), ограничивая ваше перечисление до менее 100 проверок каталогов в секунду. Ситуация ухудшится, если основная таблица файлов на данном диске сильно фрагментирована.

Что касается количества файлов, оно будет больше зависеть от количества файлов в каталоге, чем от количества самих файлов.

4
ответ дан 10 December 2019 в 02:42
поделиться

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

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

РЕДАКТИРОВАТЬ: разъяснение, как вам следует посещать каталоги. Технически это не поиск в ширину.

3
ответ дан 10 December 2019 в 02:42
поделиться

Вероятно, диск является узким местом. Но вы можете попробовать:

  1. Операции со строками можно оптимизировать - используйте массивы символов вместо std :: string.
  2. Создавать strFullName для каждого рекурсивного вызова не обязательно. Используйте единственный фиксированный буфер символов (т.е. статический массив внутри функции), мгновенно измените его.
  3. Не передавайте strPattern по значению!
  4. Не создавайте strType до отладки
  5. Другие предлагали создать список каталогов для обработки, прежде чем углубляться в рекурсию. Для его создания я предлагаю один статический массив (аналогично 2.) или использовать стек ( alloca ).
  6. В файловой системе используется Unicode для хранения имен файлов? В таком случае использование строк Unicode с FindFirstFileW и FindNextFileW может быть немного быстрее.
2
ответ дан 10 December 2019 в 02:42
поделиться

Вы держите открытыми дескрипторы DIR во время рекурсивного погружения. Вместо этого храните локальный список каталогов, с которыми вы столкнулись, и обрабатывайте их вне этого цикла, после closedir().

0
ответ дан 10 December 2019 в 02:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: