为什么 grep/-r/--include 组合比 find/-exec/grep 组合慢?

kil*_*971 6 performance grep command-line find

根据我的理解,以下两个命令大致完成了同样的事情:

命令 1:

find -name "filename.xml" -exec grep someString {} \;
Run Code Online (Sandbox Code Playgroud)

命令 2:

grep -r --include=filename.xml someString .
Run Code Online (Sandbox Code Playgroud)

尽管如此,当在相同的上下文中预热后对它们计时时,第一个比第二个快大约 3 倍(大约 4 秒对 12 秒)。

我测试的文件夹树中匹配文件名模式的文件数量非常少,而且每个文件都非常小。这让我觉得大部分时间都花在查找与文件名模式匹配的文件上,而不是花在这些匹配文件的 grepping 上。

那么为什么这两个命令行的性能会有如此大的差异呢?

Яро*_*лин 3

使用胁差(Wakizashi)而不是武士刀(Katana)来削土豆皮可能更好,但这两种工具都不是完成这项工作的好工具。这同样适用于数字工具,明智地使用它们。

这听起来像是一个空洞的建议,但在本例中,对于 find 示例中的每个文件,grep 都会执行一次。这不是明智的表现。如果将 find 的结束参数替换为“+”而不是“\;”,则 grep 只会对找到的所有文件运行一次。

要在这种情况下确定地回答,必须比较 grep 和 find 源代码的相关部分,看看哪个在匹配(查找)文件名方面更快。坦白说,这超出了我的能力范围。

直觉上我会说 find 被优化为在目录中查找文件,而 grep 被优化为在文件中查找字符串。此外,该--include选项应该适用于大写和小写文件,而 `-name

编辑:(我的发现是错误的)

对包含约 35,000 个文件的 doc 文件夹进行一些基本调查:

$ strace find . -name "moo" -exec grep a {} \+ 2>&1 |grep ^open |wc -l
4448

$ strace grep -r --include=moo  a . 2>&1 | grep ^open | wc -l
2289
Run Code Online (Sandbox Code Playgroud)

查找组合会打开更多文件。这表明与你的发现相反。我做了一些基本的计时(像 Tom Wijsman 一样)。

DIR=imagemagick-6.7.8.7
$ findhtml $DIR |& top10    $ grephtml $DIR |& top10
  1617 mmap2                  316 read
  1176 fstat64                173 close
  1176 close                  164 fstat64
   735 open                   157 openat
   608 read                   148 ioctl
   588 mprotect                63 fcntl64
   441 brk                     25 getdents64
   294 munmap                  16 fstatat64
   294 ioctl                   11 mmap2
   147 write                    5 write
time: Real 0m2.0s           time: Real 0m0.3s
Run Code Online (Sandbox Code Playgroud)

我发现 find strace 指向 /usr/lib/locale/locale-archive,但我不太确定这意味着什么。