繁体   English   中英

为什么Linux中的readdir()调用非线性增长

[英]Why readdir() call in linux grows non-linearly

我有一个包含1000个文件的目录,而readdir()不到1秒,但是10000个文件大约需要24秒。

为什么? 它应该是线性的。

谁能解释原因。 如果仅需要获取目录中的文件和子目录名称,是否有更好的解决方案?

编辑我在我的本地Linux PC上。

它可能是特定于文件系统的。 也许使用适当配置的Ext4BTRFS文件系统应该有所帮助。 一些文件系统使用散列或B树技术使大小为N的目录中文件访问的复杂度为O(log N) ,而另一些仍然是线性的,例如O(N) ,并且内核可能在此之上做一些奇怪的事情。

您可能在大型目录中使用的shell在进行glob时通常会对条目进行排序(另请参见glob(7) )。 而且您不希望它的自动完成功能在每次击键时都持续数秒钟!

我相信您永远不会拥有巨大的目录(例如,条目超过几百个),因此单个目录中的10000个文件是不合理的。 如果是这种情况,则最好以不同的方式组织文件,例如subdir01/file001.txt ... sbudir99/file999.txt

顺便说一句,如果您需要通过文本键访问许多小东西,则使用索引文件(如gdbm )或Sqlite “数据库”,或真实的数据库( PostGreSQLMongoDb ...)更适合,而且效率可能更高。 不要忘记转储数据(可能是以某种文本格式)以进行备份。

请注意,Linux上的readdir(3)和POSIX readdir的文档没有提及任何时间复杂度或任何线性行为。 缺乏提及是很重要的。 在常用的FAT文件系统上(例如在许多USB密钥上),时间复杂度可能是二次的。

它没有理由是线性的。 在较低级别,目录就像文件一样,是群集的集合。 如果它包含在一个群集中,则您只有一个实际的物理读取操作,其余的发生在内存中。 但是,当目录太大时,您将进行许多物理读取。 正如Basile Starynkevitch所说,此刻它高度依赖于文件系统结构。

但是恕我直言,如果您要浏览目录,它实际上取决于目录使用的群集数量。 当您直接在一个巨大的目录中查找文件(按名称)时,它更多地取决于实现。 与使用本地哈希(例如BSD FFS)的文件系统相比,具有线性搜索功能的文件系统的结果将更糟。

  • 在较差的文件系统上,所有操作都应是线性的(例如FAT / FAT32为O(N) )。
  • 在像OFS这样的良好文件系统上,查找,更新和删除应该比线性更好O(log N) 一个完整的目录列表仍然是线性的。
  • 无论哪种情况,它都应该比您在小型和大型情况下报告的速度快得多。

我怀疑还有其他情况。 您的结果很可能受到目录结构以外的其他因素的影响,例如:

  • 磁盘有一个硬件问题,该问题在大型示例中触发,但在小型示例中未触发
  • 在较大的情况下,系统其他部分的其他磁盘活动会中断测试
  • 磁盘硬件预取。 磁盘包含RAM高速缓存,这些高速缓存将尝试预测下一个将要请求的扇区,并准备好它们。
  • 操作系统缓存。 操作系统还将以类似方式缓存数据。
  • 您不仅可以使用readdir数据,而且该其他操作具有较高的时间复杂度,这是主要问题。
  • 您的应用程序内存使用模式能够适合小型目录的L1缓存,但不适用于大型目录。
  • 您的应用程序内存使用模式会强制在大型目录上进行交换,但不能在小型目录上进行交换。

readdir最多是线性的。 如果我们忽略文件系统中发生的所有事情,则从内核到用户空间的数据量(文件名和struct dirent中的其他内容)与文件数成正比。 因此,我们从O(n)开始。

然后内核需要找出要提供的数据。 充其量线性存储在看起来像文件的东西中。 这就是FFS和EXT2等较旧的文件系统所做的。 这为readdir提供了良好的性能(因为找到要提供给您的磁盘块只是一个数组查找),但缺点是实际上打开这些文件( openstat或几乎所有与该文件名一起使用的其他文件)都会变成O( n)操作,因为每次打开都必须线性扫描目录以找到文件名。 这就是为什么在缓存这些文件系统的目录数据方面进行大量工作的原因。 即使在那些文件系统上,您可能最终也会看到较大的目录需要较长的时间才能读取每个项目,因为文件信息的存储方式随文件大小的增加而变得昂贵。 根据文件(或目录)的大小,内核可能需要从磁盘(或缓存)中读取1到5个其他块,以找出给您的块。

如果你有一个不同的文件系统(最现代的),他们交易的线性目录的方便性和速度的磁盘上的一个更复杂的结构,让你的更好的性能openstat (毕竟,你为什么会readdir如果你不想对文件做任何事情?),但是结果是您(不一定,但很可能)比线性时间差,实际执行了一个readdir因为该操作找出了要读取哪个磁盘块您的信息可能是O(log n)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM