与图形文件搜索实用程序相比,为什么 GNU 查找速度如此之快?

Red*_*Red 49 performance find dolphin

我正在尝试查找我的主目录和所有子目录中不存在的文件。

find ~/ -name "bogus"几秒钟后给我这些信息,但KDE 的dolphin文件管理器需要将近 3 分钟才能做到这一点。这与我之前使用GNOME 的beagle经验相符。

find当图形搜索(使用起来比命令行参数更直观)落后时,如何设法快速地做同样的事情?

Gil*_*il' 71

特别使用 Baloo 来查看 Dolphin,它似乎在其搜索域中查找每个文件的元数据,即使您正在执行简单的文件名搜索。当我跟踪file.so过程中,我看到了电话lstatgetxattrgetxattr再次为每个文件,甚至对于..条目。这些系统调用检索有关文件的元数据,该文件存储在与文件名不同的位置(文件名存储在目录内容中,但元数据在inode 中)。多次查询文件的元数据很便宜,因为数据将在磁盘缓存中,但查询元数据和不查询元数据之间可能存在显着差异。

find更聪明。它试图避免不必要的系统调用。它不会调用,getxattr因为它不会基于扩展属性进行搜索。当它遍历一个目录时,它可能需要调用lstat不匹配的文件名,因为这可能是一个递归搜索的子目录(lstat是系统调用,它返回文件元数据,包括文件类型,例如常规/目录/符号链接/...)。但是find有一个优化:它从它的链接计数中知道一个目录有多少个子目录,lstat一旦它知道它遍历了所有子目录,它就会停止调用。特别是在叶目录(没有子目录的目录)中,find只检查名称,不检查元数据。此外,某些文件系统在目录条目中保留文件类型的副本,因此如果这是它需要的唯一信息,find则甚至不需要调用lstat

如果您find使用需要检查元数据的选项运行,它将进行更多lstat调用,但lstat如果不需要信息,它仍然不会调用文件(例如,因为文件被先前的条件排除在外)名称匹配)。

我怀疑其他重新发明find轮子的GUI 搜索工具同样不如经过数十年优化的命令行实用程序聪明。至少,如果您搜索“无处不在”,Dolphin 足够聪明,可以使用定位数据库(在 UI 中并不清楚结果可能已过时的限制)。

  • GNU find 非常“聪明”,以至于它错过了某些文件系统类型上的一些文件。GNU find 中众所周知的错误是它非法假设目录的链接数为“2 + 子目录数”。这适用于实现 UNIX V7 文件系统设计错误的文件系统,但不适用于所有文件系统,因为这不是 POSIX 要求。如果你想得到一个有用的 GNU make 性能数字,你需要指定 `-noleaf` 来告诉 GNU make 正确运行。 (22认同)
  • @schily,我无法在 Debian 上使用 genisoimage 1.1.11 获得带有嫁接点和 RR 的 _random 链接计数_,即使我对 iso 映像进行二进制编辑以将链接计数更改为随机值,我仍然看不到任何GNU `find` 的问题。无论如何,`strace -v` 表明`getdents()` 正确返回目录的d_type=DT_DIR,因此GNU find 不必使用链接计数技巧。 (15认同)
  • @schily,GNU `find` 可能很久以前就有这个错误,但我怀疑你现在会发现需要手动指定 `-noleaf` 的情况。AFAICT,在 Linux 上至少有 `getdents()`(和 readdir())告诉哪些文件是 UDF、ISO-9660、btrfs 上没有真正的 `.` 或 `..` 条目和 `find` 的目录文件在那里表现良好。您知道 GNU `find` 出现问题的一种情况吗? (12认同)
  • 只需使用 debian 的这个腐烂的 genisoimage 来创建一个 Rock Ridge 文件系统,使用“graft-points”,并且目录中的链接计数是一个随机值。由于 Rock Ridge 实现了链接计数和 ./..,GNU find 通常不会在这样的文件系统上找到所有文件。 (4认同)
  • @StéphaneChazelas:上次我检查(对于我的硕士论文)时,通过断言恰好 2 表示已知叶子而不是 <= 2 来修复该错误。未实现 2+ 计数器的文件系统都返回 1 表示目录链接计数,因此一切都很好。现在,如果有一天有人制作了一个文件系统,可以硬链接到没有此属性的目录,那么有人会过得很糟糕。 (4认同)
  • @schily 谢谢你精彩的奥术知识 [纯粹的赞美] ;-) (3认同)