Win32 API FindFirstFile和FindNextFile性能与命令行比较

7
我们在使用通配符模式遍历目录查找文件时遇到了意外的性能问题。
我们有180个包含10,000个文件的文件夹。使用命令行搜索 dir <pattern> /s 几乎瞬间完成(<0.25秒)。但是,从我们的应用程序中进行相同的搜索需要3-4秒钟。
我们最初尝试使用 System.IO.DirectoryInfo.GetFiles()SearchOption.AllDirectories,现在尝试使用 Win32 API 调用 FindFirstFile()FindNextFile()
使用分析工具对我们的代码进行分析表明,绝大部分执行时间都花费在这些调用上。
我们的代码基于以下博客文章:

http://codebetter.com/blogs/matthew.podwysocki/archive/2008/10/16/functional-net-fighting-friction-in-the-bcl-with-directory-getfiles.aspx

我们发现这个过程比较慢,所以更新了GetFiles函数,将谓词替换为string搜索模式。

有人可以解释一下我们的方法可能出了什么问题吗?

@Matt 我们只是在执行 dir /s 命令(已经相应地更新了我的帖子)。 - Richard Ev
1
听起来有点可疑。我非常怀疑“dir”使用的除了FindFirstFile/FindNextFile之外的任何东西。也许你误用了它们。你能提供一个片段来说明你如何使用它们吗? - sharptooth
1
@Matt dir 不使用索引服务。 - Sheng Jiang 蒋晟
@ShengJiang蒋晟,Directory.GetFiles方法是否使用索引服务?我该如何知道这一点? - fabda01
与Windows API Code Pack中的ShellSearchFolder进行比较,你就会知道。 - Sheng Jiang 蒋晟
显示剩余2条评论
3个回答

11

在我的测试中,使用具有FindExInfoBasicFIND_FIRST_EX_LARGE_FETCH参数的FindFirstFileEx函数比普通的FindFirstFile函数快得多。

使用FindFirstFile函数扫描20个包含约300,000个文件的文件夹共耗时661秒,而使用FindFirstFileEx函数只需11秒。对相同文件夹的后续调用只需要少于一秒的时间。

HANDLE h=FindFirstFileEx(search.c_str(), FindExInfoBasic, &data, FindExSearchNameMatch, NULL, FIND_FIRST_EX_LARGE_FETCH); 

在 Windows 7 x64 上,使用 FIND_FIRST_EX_LARGE_FETCH 和不使用的区别是查找缓冲区的字节数为 0x10000 对比 0x1000(使用 IDA 找到)。但在这里可能更相关的是 FindExInfoBasic - 0xC0000022L
我的测试结果(W10 x64,SSD硬盘驱动器)显示FindFirstFileEx比FindFirstFile略快(约14%)。测试文件夹中有900K个文件。枚举通常需要1.5秒。除了第一次枚举,第一次枚举需要的时间要长10倍。(当然,对于两种方法都是如此。) - Jan Slodicka
必须纠正我自己关于第一个枚举。经过多次基准测试,我可以确认第一个枚举(在清除磁盘缓存后) a) 使用FindFirstFileEx()(...FindExInfoBasic, ...FIND_FIRST_EX_LARGE_FETCH)会慢大约3倍,b) 使用FindFirstFile()会慢大约20倍。 - Jan Slodicka

3
您可以尝试使用我曾经在博客中介绍过的FindFirstFileFindNextFile实现来解决问题。

我们的方法与Darin的非常相似。 - Richard Ev
我已经测试了我的解决方案,枚举一个包含 >100K 文件的目录需要 230 毫秒。 - Darin Dimitrov
可以使用 FindFirstFileEx (... FindExInfoBasic ...) 进一步加快速度。 - MSalters
在我们的场景中,我们有180个文件夹,每个文件夹包含大约10,000个文件。跨多个文件夹的拆分似乎是导致性能下降的原因。 - Richard Ev

0
尝试使用IShellFolder::EnumObjectsSHGetDataFromIDList/IShellFolder::GetAttributesOf方法。
优点/缺点此处

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接