find
调用中参数的顺序如何影响结果的速度?
比较例如 (A)
find -name dir -type d
Run Code Online (Sandbox Code Playgroud)
和 (B)
find -type d -name dir
Run Code Online (Sandbox Code Playgroud)
或任何其他参数组合(例如使用-or
或-and
)。我希望find
以某种方式变得聪明。
我试图通过执行 A 和 Btime
并重复 5 次来收集一些统计数据。然而与
11.86, 7.23, 5.25, 5.87, 7.16
Run Code Online (Sandbox Code Playgroud)
对于 A 和 B:
9.73, 6.56, 8.69, 7.14, 6.35
Run Code Online (Sandbox Code Playgroud)
这并不是真正的结论,7.5s
两者的平均值都在附近,并且差异很大。
那么,重复我的问题,使用 的参数顺序是否重要find
?
Sté*_*las 11
代价高昂的是对文件进行系统调用(对于系统调用本身和 I/O)。
诸如-type
,-mtime
需要lstat(2)
对文件进行系统调用。-name
, -path
,-regex
不要(当然,它会对它们包含的目录进行系统调用以读取它们的内容)。
通常,find
执行lstat()
无论如何(因为它需要知道一个文件是否是一个目录或不进入它,除非该信息在 中提供readdir()
),但在某些情况下它可以没有它。例如,如果目录的链接数小于 3,那么在某些文件系统中,find
知道它没有子目录,并且某些find
实现将通过不在lstat
那里做s来优化。
-xtype
将导致 a stat(2)
, -printf ...
,-ls
可能导致 a stat()
, lstat()
, readlink()
, -lname
alstat()
和readlink()
。
这就是为什么您可能希望将-name
/ -path
/ -regex
... 放在首位。如果他们可以排除一个文件,他们就可以避免一个或多个系统调用。
现在, a-regex
可能比 a 贵-name
,但我不太确定交换它们会得到多少。
另请注意,某些find
实现(如 GNU)find
会在可能的情况下默认对检查重新排序。看:
info find 'Optimisation Options'
Run Code Online (Sandbox Code Playgroud)
在 GNU 系统上(在 gnu.org上有最新版本的 GNU findutils
)。
通常,如果您在 GNU 系统上进行测试,两个命令都会做同样的事情,因为无论如何find
都会-name
向前移动。
因此,要使-type d -name ...
vs-name ... -type d
有所不同,您需要一种find
不通过重新排序这些谓词进行优化的实现,以及一种通过不对lstat()
每个文件都进行优化来进行优化的实现。
无论实现如何,都会有(巨大)差异的地方:
find . -name 'x*' -exec test -d {} \; -print
Run Code Online (Sandbox Code Playgroud)
对比:
find . -exec test -d {} \; -name 'x*' -print
Run Code Online (Sandbox Code Playgroud)
find
不能重新排序,-exec
因为这样做可能会引入功能差异(find
无法知道执行的命令是仅用于测试还是执行其他操作)。
当然-exec ... {} \;
,这比任何其他谓词都要贵几个数量级,因为它意味着派生一个进程并在其中执行一个命令(它本身运行许多系统调用)并等待它及其退出代码。
$ time find /usr/lib -exec test -d {} \; -name z\* -print > /dev/null
1.03s user 12.52s system 21% cpu 1:03.43 total
$ time find /usr/lib -name z\* -exec test -d {} \; -print > /dev/null
0.09s user 0.14s system 62% cpu 0.367 total
Run Code Online (Sandbox Code Playgroud)
(第一个调用(56685) 中的test
每个文件/usr/lib
,第二个仅调用名称以z
(147)开头的文件)。
请注意,-exec test -d {} \;
这与-type d
. 它是 GNU 特定的-xtype d
.