调用中参数的顺序如何find
影响结果的速度?
比较例如(A)
find -name dir -type d
和(B)
find -type d -name dir
或任何其他参数组合(例如使用-or
或-and
)。我希望find
在某种程度上变得聪明。
我尝试通过time
重复执行 A 和 B 5 次来收集一些统计数据。然而与
11.86, 7.23, 5.25, 5.87, 7.16
对于 A 和 B:
9.73, 6.56, 8.69, 7.14, 6.35
这并不是真正的结论,两者的平均值都在附近7.5s
,并且方差相当高。
那么,重复我的问题,参数的顺序是否重要find
?
答案1
代价高昂的是对文件进行系统调用(对于系统调用本身和 I/O)。
-type
诸如,之类的事情-mtime
需要lstat(2)
对文件进行系统调用。-name
,,不要(尽管-path
它-regex
当然会对它们包含的目录进行系统调用以读取其内容)。
通常,无论如何find
都会执行lstat()
(因为它需要知道文件是否是目录才能进入该目录,除非在 中提供了该信息readdir()
),但在某些情况下它也可以不使用它。例如,如果目录的链接数小于 3,则在某些文件系统中,find
知道它没有子目录,并且某些find
实现将通过不在lstat
其中执行 s 来进行优化。
-xtype
会导致stat(2)
, -printf ...
,可能-ls
导致stat()
, lstat()
, readlink()
,-lname
和lstat()
.readlink()
这就是为什么你可能想把-name
/ -path
/ -regex
... 放在第一位。如果他们可以排除一个文件,他们就可以避免一个或多个系统调用。
现在, a-regex
可能比 a 贵-name
,但我不太确定交换它们会得到多少。
另请注意,某些find
实现(例如 GNU)find
会在可能的情况下默认重新排序检查。看:
info find 'Optimisation Options'
在 GNU 系统上(gnu.org 上有对于最新版本的 GNU findutils
)。
通常,如果您在 GNU 系统上进行测试,两个命令都会执行相同的操作,因为无论如何find
都会-name
向前移动。
因此,为了使-type d -name ...
vs-name ... -type d
发挥作用,您需要一种find
不通过对这些谓词重新排序来进行优化的实现,以及一种通过不在lstat()
每个文件上执行 an 来进行一些优化的实现。
无论实施如何,都会存在(巨大)差异:
find . -name 'x*' -exec test -d {} \; -print
对比:
find . -exec test -d {} \; -name 'x*' -print
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
(第一个要求(56685)test
中的每个文件/usr/lib
,第二个仅要求名称以z
(147) 开头的文件)。
请注意,-exec test -d {} \;
与 不一样-type d
。它是 GNU 特定的可移植版本-xtype d
。