我有一个包含1000个文件的目录,readdir()
只需不到1秒,但10000个文件大约需要24秒。
为什么呢?它应该是线性的。
任何人都可以解释原因。 如果只需要将文件和子目录名称放在目录中,是否有更好的解决方案?
修改 我在我的本地linux pc上。
答案 0 :(得分:3)
它可能是特定于文件系统的。也许使用适当配置的Ext4或BTRFS文件系统应该有所帮助。某些文件系统使用散列或B树技术使文件访问的复杂性在 N 的目录中 O(log N),其他文件仍然是线性的,例如 O(N),内核可能会做出奇怪的事情。
您可能在大型目录中使用的shell通常会在globbing时对条目进行排序(另请参阅glob(7))。并且你不希望它的auto-completion在每次击键时持续很多秒!
我相信你永远不会拥有庞大的目录(例如,有超过几百个条目),因此单个目录中的10000个文件是不合理的。如果是这种情况,您可以更好地整理文件,例如: subdir01/file001.txt
... sbudir99/file999.txt
请注意,Linux上readdir(3)和POSIX readdir的文档没有提及任何时间复杂度或任何线性行为。缺乏提及意义重大。 在常用的FAT文件系统上(例如在许多USB密钥上),时间复杂度可能是二次的。
答案 1 :(得分:1)
没有理由是线性的。在较低级别,目录就像一个文件,一组集群。如果它包含在一个集群中,则只有一个实际的物理读取操作,其余部分发生在内存中。但是当您的目录变得过大时,您将拥有许多物理读取。此时,如Basile Starynkevitch所述,它变得高度依赖于文件系统结构。
但恕我直言,如果你想浏览目录,它主要取决于目录使用的集群数量。当您在一个巨大的目录中直接查找文件(按名称)时,它更依赖于实现。具有线性搜索的Filsystems将比使用本机哈希的文件系统(例如BSD FFS)具有更差的结果。
答案 2 :(得分:0)
O(N)
)。O(log N)
的好文件系统上,搜索,更新和删除应该优于线性。完整的目录列表仍然是线性的。我怀疑其他事情正在发生。您的结果很可能会受到目录结构之外的其他因素的影响,例如:
readdir
以外的数据进行操作,而其他操作的时间复杂度更高,而且占主导地位。答案 3 :(得分:0)
readdir
充其量是线性的。如果我们忽略文件系统中发生的所有事情,那么从内核到用户空间的数据量(文件名和struct dirent中的其他内容)与文件数量成正比。所以我们从O(n)开始。
然后内核需要找出给你的数据。它最好是线性存储在看起来像文件的东西中。这就是像FFS和EXT2这样的旧文件系统。这为readdir
提供了良好的性能(因为找到给你的磁盘块只是一个数组查找),但缺点是实际打开这些文件(open
,stat
或几乎任何东西与文件名一起使用的其他操作变为O(n)操作,因为每次打开都必须线性扫描目录以查找文件名。这就是为什么在为这些文件系统缓存目录数据方面做了大量工作的原因。即使在那些文件系统上,您可能最终会看到较大的目录需要更长的时间来读取每个项目,因为文件信息的存储方式随着文件大小而变得更加昂贵。根据您的文件(或目录)大小,内核可能需要从磁盘(或缓存)中读取1到5个其他块,以找出要为您提供的块。
如果您有不同的文件系统(大多数现代文件系统),它们会将线性目录的便利性和速度换成磁盘上更复杂的结构,从而为您提供更好的open
和{{1}性能(毕竟,如果你不打算对文件做任何事情,你为什么要stat
?),但结果你最终(不一定,但很有可能)实际上比线性时间更差执行readdir
,因为找出要为您的信息读取的磁盘块的操作可能是O(log n)。