【问题标题】:performance grep vs perl -ne性能 grep 与 perl -ne
【发布时间】:2014-06-26 13:02:19
【问题描述】:

我做了一个性能测试,结果非常令人惊讶:perl 快了 20 倍以上!

这正常吗? 它是由我的正则表达式引起的吗? egrep 比 grep 慢得多吗? ...我在当前的 cygwin 和 virtualbox 中的当前 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

(输出同上...)

解压后的文件大小约为 2.000.000 行,解压后的文件大小为 500MBytes - 匹配的行数非常少。

我的测试版本:

  • OpenSuSE 与 grep (GNU grep) 2.14
  • cygwin 与 grep (GNU grep) 2.16

也许是一些带有较新 grep 版本的错误?

【问题讨论】:

  • 在我自己的机器上进行测试时,grep 似乎更快:grep=0m0.011s, perl=0m0.024s。你的文件有多大?
  • 有趣的是,这种重复运行平均会在大约同一时间显示它们。
  • 这很难相信。我会假设仅 Perl 的开销就会将性能优势转移到 grep。我知道'|'应该是效率最低的正则表达式原子之一。也许是这个因素?

标签: regex perl grep


【解决方案1】:

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

(?:ERROR|WARNING|SEVERE)

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

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

【讨论】:

    【解决方案2】:

    您被操作系统的缓存欺骗了。在读取和 grep 文件时,文件系统的某些层会被遍历:

    • 硬盘自带缓存
    • 操作系统读取缓存

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

    【讨论】:

    • 肯定不是:最后一次(如上所示)运行以给定的顺序发生:快速 perl 运行是第一个(所以还没有缓存......)这也是我分析这个的原因更深入:egrep 测试在顶部左右没有可见的 iowait 可见... perl 测试确实显示了高达 30% 的 iowait 我猜。
    【解决方案3】:

    正如 Chris Hamel 评论的那样......不使用“|” atom 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 运行的原子比一个接一个地运行三个 grep 慢 3 倍以上 - 对我来说听起来像是一个错误......任何早期的 grep 版本可以测试?我也有一个 reHat5... grep 似乎也很慢...

    【讨论】:

      猜你喜欢
      • 2015-01-15
      • 1970-01-01
      • 2011-08-18
      • 1970-01-01
      • 1970-01-01
      • 2011-05-18
      • 2015-10-04
      • 2012-05-07
      • 1970-01-01
      相关资源
      最近更新 更多