在C ++中抓取递归ntfs目录的最快方法

时间:2010-06-14 22:11:35

标签: c++ performance recursion directory ntfs

我已经编写了一个小型爬虫来扫描和求助目录结构。

它基于dirent(这是FindNextFileA的一个小包装) 在我的第一个基准测试中,这是令人惊讶的缓慢:

4500个文件大约123473ms(thinkpad t60p本地三星320 GB 2.5“HD)。 在123473毫秒内找到121481个文件 这个速度是否正常?

这是我的代码:

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;
  }
}

4 个答案:

答案 0 :(得分:4)

在某些情况下,这样的速度是正常的。首先,使用FindFirstFileA而不是FindFirstFileW将导致从UTF-16到ANSI的转换开销。其次,如果您要浏览操作系统尚未访问的目录,则会产生至少一次查找惩罚(大多数消费者硬盘大约需要16毫秒),将枚举限制在每秒100次以下的目录检查中。如果给定驱动器上的主文件表严重碎片化,情况会变得更糟。

关于文件数量,它将更多地取决于每个目录的文件数量而不是文件本身的数量。

答案 1 :(得分:3)

第一次执行递归目录爬网时,您应该首先枚举整个当前目录,并在完成后排队找到要访问的任何目录。这样,您可能会利用NTFS可能做的任何即时预读优化。

在后续的递归目录爬网中,如果目录的元数据适合系统缓存,则无论如何操作都无关紧要。

编辑:澄清你应该如何访问目录。从技术上讲,这不是广泛的第一次搜索。

答案 2 :(得分:2)

可能驱动器是瓶颈。但你可以尝试:

  1. 可以优化字符串操作 - 使用std :: string的字符串数组。
  2. 构建strFullName不需要每次递归调用。使用单个固定的字符缓冲区(即函数内的静态数组),立即修改它。
  3. 不要按值传递strPattern!
  4. 调试前不要创建strType
  5. 其他人建议在深入递归之前构建一个要处理的目录列表。为了构建它,我建议使用单个静态数组(类似于2.)或使用堆栈(alloca)。
  6. filesysytem使用Unicode来存储文件名?如果是这样,使用FindFirstFileWFindNextFileW的unicode字符串可能会快一点。

答案 3 :(得分:0)

您在递归潜水期间持有DIR手柄。相反,请保留您遇到的本地目录列表,并在closedir()之后在该循环之外处理它们。