我正在尝试加速C ++中的目录枚举,我正在递归到子目录中。我目前有一个应用程序花费95%的时间在FindFirst / FindNextFile API中,并且需要几分钟来枚举给定卷上的所有文件。我知道可以更快地执行此操作,因为有一个应用程序执行:Everything。它可以在几秒钟内枚举我的整个驱动器。
我怎么能做到这样的事呢?
答案 0 :(得分:8)
我意识到这是一篇很老的帖子,但是有一个关于源代码伪造的项目,它完全符合您的要求并且源代码可用。
您可以在此处找到该项目:NTFS-Search
答案 1 :(得分:6)
“Everything”以低于Win32 FindFirst / FindNext API的级别访问目录信息。
我相信它直接读取和解释NTFS MFT结构,这是其性能的主要原因之一。这也是为什么它需要管理员权限以及为什么“Everything”仅索引本地或可移动NTFS卷(例如,不是网络驱动器)。
其他几个执行类似操作的实用程序是:
使用这些工具上的调试器进行一些反向工程可能会让您对他们使用的技术有所了解。
答案 2 :(得分:5)
“Everything”在后台构建索引,因此查询针对索引而不是文件系统本身。
有一些改进 - 至少在直接的算法上:
首先,广度搜索深度搜索。也就是说,在递归到您找到的子文件夹之前,枚举并处理单个文件夹中的所有文件。这改善了地方 - 通常很多。
在Windows 7 / W2K8R2上,您可以将FindFirstFileEx
与FindExInfoBasic
一起使用,主要加速是在启用此功能的NTFS文件系统上省略短文件名。
如果枚举不同的物理磁盘(不仅仅是驱动器),单独的线程会有所帮助。对于同一磁盘,只有它是一个SSD(“零搜索时间”),或者您花费大量时间处理文件名(与磁盘访问所花费的时间相比),它才有用。
[edit] Wikipedia实际上有一些评论 - 基本上,他们正在跳过文件系统抽象层,并直接访问NTFS。这样,他们可以批量调用并跳过文件系统的昂贵服务 - 例如检查ACL。
一个好的起点是MSDN上的NTFS Technical Reference。
答案 3 :(得分:2)
不要立即递归,保存您找到的目录列表,并在完成后潜入它们。您希望对每个目录进行线性访问,以利用引用的位置以及操作系统正在执行的任何缓存。
答案 4 :(得分:1)
如果你在NTFS上这样做,这里有一个低级访问的lib:NTFSLib。
您可以枚举$ MFT中的所有文件记录,每个记录代表磁盘上的真实文件。您可以从记录中获取所有文件属性,包括$ DATA。
在我测试的时候,这可能是枚举NTFS卷上所有文件/目录的最快方法,每分钟200k~300k文件。
答案 5 :(得分:0)
如果你已经做得最好,你可以从API获得最大速度,下一步是进行低级别磁盘访问并完全绕过Windows。您可以从NTFS drivers for Linux获得一些指导,也可以直接使用。