性能grep vs perl -ne

时间:2014-06-26 13:02:19

标签: regex perl grep

我做了一个非常令人惊讶的结果的性能测试:perl的速度提高了20多倍!

这是正常的吗? 它是由我的正则表达式产生的吗? egrep远比grep慢? ...我在当前的cygwin和虚拟盒中的当前OpenSuSE 13.1上进行了测试。

使用perl进行最快的测试:

time zcat log.gz \
| perl -ne 'print if ($_ =~ /^\S+\s+\S+\s+(ERROR|WARNING|SEVERE)\s/ )' 
| tail
2014-06-24 14:51:43,929 SEVERE ajp-0.0.0.0-8009-13             SessionDataUpdateManager                cannot register active data when window has no name
2014-06-24 14:52:01,031 ERROR  HFN SI ThreadPool(4)-442        CepEventUnmarshaler                     Unmarshaled Events Duration: 111
2014-06-24 14:52:03,556 ERROR  HFN SI ThreadPool(4)-444        CepEventUnmarshaler                     Unmarshaled Events Duration: 52
2014-06-24 14:52:06,789 SEVERE ajp-0.0.0.0-8009-1              SessionDataUpdateManager                cannot register active data when window has no name
2014-06-24 14:52:06,792 SEVERE ajp-0.0.0.0-8009-1              SessionDataUpdateManager                cannot register active data when window has no name
2014-06-24 14:52:07,371 SEVERE ajp-0.0.0.0-8009-9              SessionDataUpdateManager                cannot register active data when window has no name
2014-06-24 14:52:07,373 SEVERE ajp-0.0.0.0-8009-9              SessionDataUpdateManager                cannot register active data when window has no name
2014-06-24 14:52:07,780 SEVERE ajp-0.0.0.0-8009-11             SessionDataUpdateManager                cannot register active data when window has no name
2014-06-24 14:52:07,782 SEVERE ajp-0.0.0.0-8009-11             SessionDataUpdateManager                cannot register active data when window has no name
2014-06-24 15:06:24,119 ERROR  HFN SI ThreadPool(4)-443        CepEventUnmarshaler                     Unmarshaled Events Duration: 117

real    0m0.151s
user    0m0.062s
sys     0m0.139s

细!

使用egrep测试速度慢得多:

time zcat log.gz \
| egrep '^\S+\s+\S+\s+(ERROR|WARNING|SEVERE)\s' 
| tail
...

real    0m2.454s
user    0m2.448s
sys     0m0.092s

(输出与上述相同......)

最后甚至更慢的grep用不同的符号(我的第一次尝试)

time zcat log.gz \
| egrep '^[^\s]+\s+[^\s]+\s+(ERROR|WARNING|SEVERE)\s'
| tail
...

real    0m4.295s
user    0m4.272s
sys     0m0.138s

(输出与上述相同......)

ungzipped文件大小约为2.000.000行,非gzip-ped 500MBytes - 匹配的行数非常小。

我的测试版本:

  • 使用grep(GNU grep)2.14
  • 的OpenSuSE
  • cygwin with grep(GNU grep)2.16

或许有一些较新的grep版本的Bug?

3 个答案:

答案 0 :(得分:1)

你应该能够通过使括号不被捕获来使Perl更快一点:

(?:ERROR|WARNING|SEVERE)

此外,没有必要与$_匹配。如果没有指定任何内容,则假定$_。这就是它存在的原因。

perl -ne 'print if /^\S+\s+\S+\s+(?:ERROR|WARNING|SEVERE)\s/'

答案 1 :(得分:0)

你被操作系统的缓存欺骗了。在阅读和浏览文件时,文件系统的某些层可以通过:

  • Harddrive自己的缓存
  • 操作系统读取缓存

要真正了解发生了什么,通过运行一些可以完成工作但不计算在内的测试来预热这些缓存是一个好主意。在这些测试之后停止你的跑步时间。

答案 2 :(得分:0)

正如Chris Hamel评论的那样....不使用“|”原子grep变得快了大约10倍 - 仍然比perl慢。

time zcat log.gz \
| egrep '^[^\s]+\s+[^\s]+\s+(ERROR)\s'
| tail
...
real    0m0.216s
user    0m0.062s
sys     0m0.123s

所以用2“|” grep运行的原子比在运行三个greps之后慢了3倍 - 对我来说听起来像一个Bug ...任何早期的grep版本要测试一下?我有一个reHat5也... grep似乎在那里很慢...