为什么"grep --ignore-case"慢50倍?

Mar*_*agh 14 bash performance time grep

我很惊讶地看到,当你添加--ignore-case选项时grep,它可以使搜索速度减慢50倍.我在两台不同的机器上进行了测试,结果相同.我很想知道巨大的性能差异的解释.

我还想看一个替代命令来grep进行不区分大小写的搜索.我不需要正则表达式,只需修复字符串搜索.首先,测试文件将是一个带有一些虚拟数据的50 MB纯文本文件,您可以使用以下代码生成它:

创建test.txt

yes all work and no play makes Jack a dull boy | head -c 50M > test.txt
echo "Jack is no fun" >> test.txt
echo "Jack is no Fun" >> test.txt
Run Code Online (Sandbox Code Playgroud)

示范

以下是缓慢的证明.通过添加--ignore-case选项,命令变慢57倍.

$ time grep fun test.txt
all work and no plJack is no fun
real    0m0.061s

$ time grep --ignore-case fun test.txt
all work and no plJack is no fun
Jack is no Fun
real    0m3.498s
Run Code Online (Sandbox Code Playgroud)

可能的解释

谷歌搜索我发现一个关于grep在UTF-8语言环境中缓慢的讨论.所以我运行了以下测试,它确实加快了速度.我的机器上的默认语言环境是en_US.UTF-8,所以设置它POSIX似乎已经进行了性能启动,但现在我无法正确搜索Unicode文本,这是不合需要的.它仍然慢2.5倍.

$ time LANG=POSIX grep --ignore-case fun test.txt
all work and no plJack is no fun
Jack is no Fun
real    0m0.142s
Run Code Online (Sandbox Code Playgroud)

备择方案

我们可以使用Perl而不是更快,但仍然比区分大小写的grep快5.5倍.而上面的POSIX grep大约快两倍.

$ time perl -ne '/fun/i && print' test.txt
all work and no plJack is no fun
Jack is no Fun
real    0m0.388s
Run Code Online (Sandbox Code Playgroud)

所以我很乐意找到一个快速正确的替代品和解释,如果有人有一个.

更新 - CentOS

上面测试的两台机器都运行Ubuntu 11.04(Natty Narwhal),另外12.04(Precise Pangolin).在CentOS 5.3机器上运行相同的测试会产生以下有趣的结果.两种情况的表现结果几乎相同.现在CentOS 5.3于2009年1月发布,运行grep 2.5.1而Ubuntu 12.04运行grep 2.10.因此,新版本可能会发生变化,并且两个版本可能会有所不同.

$ time grep fun test.txt
Jack is no fun
real    0m0.026s

$ time grep --ignore-case fun test.txt
Jack is no fun
Jack is no Fun
real    0m0.027s
Run Code Online (Sandbox Code Playgroud)

Pet*_*ter 8

我认为这个错误报告有助于理解为什么它很慢:

bug报告grep,在ignore-case上缓慢

  • 你能提供一个总结吗? (3认同)

Mar*_*rov 8

这种缓慢是由于grep(在UTF-8语言环境中)不断访问文件"/ usr/lib/locale/locale-archive"和"/usr/lib/gconv/gconv-modules.cache".

它可以使用strace实用程序显示.这两个文件都来自glibc.