在NTFS上打开许多小文件太慢了

时间:2015-01-08 16:33:31

标签: c++ windows performance ntfs directory-traversal

我正在编写一个应该处理许多小文件的程序,比如数千甚至数百万。 我已经在500k文件上测试了那个部分,第一步就是迭代一个目录,里面有大约45k个目录(包括子目录的子目录等)和500k个小文件。遍历所有目录和文件,包括获取文件大小和计算总大小大约需要6秒。现在,如果我尝试在遍历时打开每个文件并立即关闭它,它看起来永远不会停止。事实上,它需要太长时间(小时......)。自从我在Windows上执行此操作后,我尝试使用CreateFileW,_wfopen和_wopen打开文件。我没有在文件上读或写任何东西,尽管在最后的实现中我只需要阅读。但是,我没有看到任何尝试都有明显的改善。

我想知道是否有更高效的方法来打开具有任何可用功能的文件,无论是C,C ++还是Windows API,还是唯一更有效的方式来阅读MFT并直接读取磁盘块,我试图避免?

更新:我正在处理的应用程序是使用版本控制进行备份快照。因此,它还具有增量备份。 500k文件的测试是在一个巨大的源代码库上完成的,以便进行版本控制,就像scm一样。因此,所有文件都不在一个目录中。还有大约45k目录(如上所述)。

因此,建议的压缩文件解决方案并没有帮助,因为备份完成后,访问所有文件时都是如此。因此,我认为没有任何好处,甚至会产生一些性能成本。

5 个答案:

答案 0 :(得分:6)

您尝试做的事情本质上是任何操作系统难以有效执行的。 45,000个子目录需要大量磁盘访问,无论它是如何切片的。

任何超过1,000字节的文件都是"大"就NTFS而言。如果有办法使大多数数据文件小于约900 字节,则可以通过将文件数据存储在MFT中来实现主要效率。然后获取数据并不比获取文件的时间戳或大小更昂贵。

我怀疑有没有办法优化程序的参数,流程选项,甚至操作系统的调整参数,以使应用程序运行良好。您将面临多小时的操作,除非您能够以完全不同的方式重新构建它。

一种策略是将文件分布在多台计算机上 - 可能是数千台计算机 - 并在每个进程上有一个子应用程序本地文件,将任何结果提供给主应用程序。

另一种策略是将所有文件重新构建为一些较大的文件,例如@felicepollano建议的大型.zip文件,有效地虚拟化您的文件集。随机访问4000 GB文件本质上比访问40亿个1 MB文件更有效和更有效地使用资源。将所有数据移动到合适的数据库管理器(MySQL,SQL Server等)中也可以实现这一目标,并可能提供其他好处,如简单搜索和简单的归档策略。

答案 1 :(得分:3)

对于具有该文件数量的NTFS卷,每个文件的开销为5到20毫秒并非异常。 (在传统的旋转驱动器上,你无论如何都不能期望更好,因为它与磁头寻找时间的顺序相同。从这一点开始,我假设我们正在处理企业级硬件,SSD和/或RAID。)

根据我的经验,您可以通过并行化请求(即使用多个线程和/或进程)来显着提高吞吐量。大多数开销似乎是每个线程,系统可以一次打开十个文件,几乎与单独打开一个文件一样快。我不确定为什么会这样。您可能需要进行试验以找到最佳的并行化级别。

系统管理员还可以通过将内容复制到新卷来显着提高性能,最好是以与访问它们的顺序大致相同的顺序。我最近不得不这样做,它将备份时间(对于一个包含大约1400万个文件的卷)从85小时减少到18小时。

您也可以尝试OpenFileById(),它可能对大型目录中的文件执行得更好,因为它绕过了枚举目录树的需要。但是,我自己从未尝试过,而且它可能没有太大的影响,因为如果您只是枚举它,目录很可能会被缓存。

您还可以通过reading them from the MFT更快地枚举磁盘上的文件,尽管听起来好像这对您来说不是瓶颈。

答案 2 :(得分:1)

有一个hack你可以尝试:用低压缩率压缩这些文件然后使用一些Zip库来读取它们,这通常比逐个读取单个文件更快。 对于合作,这应该事先作为预处理步骤完成。

答案 3 :(得分:1)

您可以尝试执行一次传递以将文件枚举到数据结构,然后在第二次传递中打开和关闭它们,以查看交错操作是否导致争用。

正如我在评论中发布的那样,在单个NTFS目录中存在大量条目存在很多性能问题。因此,如果您可以控制这些文件在目录之间的分布方式,您可能希望利用它。

还要检查系统上的反恶意软件。有些人会在每次尝试访问时扫描整个文件,从而减慢每个文件的访问速度。使用Sysinternals Procmon可以帮助您发现这类问题。

在尝试提高效果时,设定目标是个好主意。速度有多快?

编辑:除非您使用的是Windows XP或更早版本,否则原始答案的这一部分不适用:

默认情况下,打开和关闭每个文件将更新索引中的最后访问时间。您可以尝试一项实验,将该功能关闭via registrycommand line,看看它有多大差异。我不确定你的实际产品是否可行,因为它是一个全球性的设置。

答案 4 :(得分:1)

NTFS速度很慢,文件数量很多。特别是如果它们在同一目录中。当它们被分成单独的目录和子目录时,访问速度更快。我有使用视频摄像头板(4个摄像头)存储的许多文件的经验,即使看到文件和大小的数量(根文件夹上的属性)也太慢了。有趣的是,当磁盘是FAT32时,同样的速度要快得多。所有消息来源都说NTFS更快......读取单个文件的速度可能更快,但目录操作速度较慢。

为什么你需要这么多文件?我希望启用目录索引服务。