6

上下文 我们有一个本地文件系统支持的缓存库。由于大量条目(例如多达 100,000 个),我们目前在一次安装时遇到性能问题。问题:我们将所有 fs 条目存储在一个“缓存目录”中。非常大的目录表现不佳。

我们正在考虑将这些条目分散到子目录中——就像 git 所做的那样,例如 100 个子目录,每个子目录大约 1,000 个条目。

问题

我知道较小的目录大小将有助于文件系统访问。

但是“传播到子目录”会加速遍历所有条目,例如枚举/读取所有 100,000 个条目吗?即当我们从 FS 存储初始化/预热缓存时,我们需要遍历所有 100,000 个条目(并删除旧条目)可能需要 10 多分钟。

“传播数据”会减少这种“遍历时间”。此外,这种“遍历”实际上可以/确实删除过时的条目(例如超过 N 天)“传播数据”会改善删除时间吗?

附加上下文 -NTFS -Windows 系列操作系统(Server 2003、2008)

-Java J2ee 应用程序。

我/我们将不胜感激任何关于文件系统可扩展性问题的教育。

提前致谢。

将要

ps 我应该评论说我有工具和能力来自己测试这个,但我想我会先选择蜂巢思维来获得理论和经验。

4

4 回答 4

10

我还相信跨子目录传播文件将加速操作。

所以我进行了测试:我生成了从 AAAA 到 ZZZZ 的文件(26^4 个文件,大约 450K)并将它们放入一个 NTFS 目录中。我还将相同的文件放置在从 AA 到 ZZ 的子目录中(即按文件名的前 2 个字母对文件进行分组)。然后我进行了一些测试——枚举和随机访问。我在创建后和测试之间重新启动了系统。

扁平结构的性能略好于子目录。我相信这是因为目录被缓存并且 NTFS 索引目录内容,所以查找速度很快。

请注意,对于 400K 文件,完整枚举(在这两种情况下)大约需要 3 分钟。这是很重要的时间,但子目录使情况变得更糟。

结论:特别是在 NTFS 上,如果可以访问这些文件中的任何一个,将文件分组到子目录中是没有意义的。如果您有缓存,我还将测试按日期或按域对文件进行分组,假设某些文件的访问频率高于其他文件,并且操作系统不需要将所有目录保留在内存中。但是,对于您的文件数量(低于 100K),这可能也不会提供显着的好处。我认为,您需要自己衡量这些特定场景。

更新:我已将随机访问测试减少为仅访问一半文件(从 AA 到 OO)。假设这将涉及一个平面目录和仅一半的子目录(对子目录的情况给予奖励)。仍然平面目录表现更好。所以我假设除非你有数百万个文件,否则将它们保存在 NTFS 上的一个平面目录中会比将它们分组到子目录中更快。

于 2010-12-05T07:32:55.700 回答
4

如果您从不需要统计或列出缓存目录,而只需要通过完整路径统计和打开其中的文件,那么目录中有多少文件并不重要(至少在 100k 文件级别)。

在这种情况下,许多缓存框架和文件系统重的存储引擎会根据文件名中的第一个字符创建子目录,因此如果您在缓存中存储文件“abcdefgh.png”,它将进入“cache/a/” b/cdefgh.png” 而不仅仅是“cache/abcdefgh.png”。这假设文件名的前两个字母在字符空间中的分布大致均匀。

正如您所提到的,由于您涉及列出或遍历目录的主要任务是删除过时的文件,我建议您根据文件缓存的日期和/或时间创建目录,即“cache/2010/12/04 /22/abcdefgh.png" 并且,无论您在何处索引缓存,请务必按文件名和日期对其进行索引(特别是如果它在数据库中),以便您可以快速从索引中按日期删除项目并删除相应的目录。

于 2010-12-05T03:56:31.943 回答
0

你是如何加载缓存的?如果您使用标准 Java 文件系统交互,那将是您的第一个瓶颈 - Java 在文件夹内容迭代方面非常糟糕 - 如果您在迭代时对每个文件进行检查(获取修改日期,请确保文件是'不是目录等...)性能可能会受到很大影响(这些都涉及到本土的往返旅行)。迁移到基于本机 FindFirstFile 的解决方案可能会提供显着(如数量级)的改进。FindFirstFile 在每个迭代步骤中返回有关文件的所有信息。Java File.listFiles() 返回路径列表。然后,当您查询属性或其他元数据时 - 每次调用都是到文件系统的往返。可怕的,可怕的低效。

好的 - 这不碍事。接下来,NTFS 中巨大目录的原始迭代并不比 n 叉树方法(文件夹和子文件夹等)慢。对于 FAT32,这是一件大事——但 NTFS 可以很好地处理这类事情。也就是说,拆分为子文件夹会带来一些自然的并行化机会,而这些机会通过单个文件夹很难实现。如果您可以生成 10 或 15 个线程,每个线程访问单独的文件夹,那么您可以有效地消除磁盘延迟这一影响因素。

我可能会建议您从分析开始(当然,您已经知道了) - 并查看大部分加载时间来自何处。您可能会感到惊讶(例如,在我们的一个执行大量文件列表处理的应用程序中,我很震惊地发现在检查 isDirectory() 时我们被击中了多少时间 - 一个简单的更改,例如在目录之前进行日期比较/file 确定使我们的迭代速度提高了 30%)。

于 2010-12-05T04:05:05.193 回答
0

要看的是你的磁盘子系统是如何安排的。虽然磁盘的大小迅速增长,但它们并没有变得更快(访问时间) 是不同的磁盘排列(使用更多磁盘)或使用 SSD 驱动器的一种选择。例如,SSD 没有移动部件,可以在 10 秒内接触 10 万个文件。使预热变得不必要。

于 2010-12-05T11:23:19.367 回答