500万正则表达式匹配我的CPU [Perl]

时间:2011-12-17 18:21:07

标签: html regex performance perl

我有一个触发多个进程的应用程序。每个进程都会加载一个HTML文件并尝试查找是否出现模式,如下所示:

OUTER:
while(my ($prov,$arr_ref) = each(%{$self->{TAGS}})) {
    foreach my $tag (@{$arr_ref}) {
        if ($html =~ m/\Q$tag\E/i) {
            $provider = $prov;
            last OUTER;
        }
    }
}

$self->{TAGS}键是一个模式名称,该值是对带有字符串(标量)的数组的引用。

我正在分析该程序,并发现这一部分:

$html =~ m/\Q$tag\E/i

让我的CPU跳到100%。如果我删除它,它几乎不会达到10%。

我只考虑了一种方法,即将每个数组ref中的所有标量(字符串)转换为已编译的正则表达式(qr/.../)。我想这不会有太大的改进,因为我猜这个问题实际上当正则表达式实际上搜索所有HTML页面时,可能是几百个字节。

如何改善此部分?

SUB-QUESTION:由于下面的答案,以及我做的一些测试,我会提出我的问题,问题不是正则表达式,我之前已尝试index方式我问过这个问题,还尝试使用qr//编译正则表达式,这个问题是,对于html文件的大小,$html内容是HTML文本,有时它很小,有时它很大,所以这里的问题是:什么是最好的方法(资源明智...)如果一个字符串出现在更大的内容(让我们说大小为1MB)?是什么?

感谢。

2 个答案:

答案 0 :(得分:4)

使用index可以提高性能,因为您将摆脱使用正则表达式的所有开销。请做一个基准!

$html_searchable = lc ($html);

...    

while ( ... ) {
  foreach ( ... ) {
    if (index ($html_searchable, lc ($tag)) > -1) {
      ... # we got a match
    }
  }
}

如果您想进一步增加它,则应将所有$tag存储为小写字符串,这样就不必多次lc相同的字符串。

<强>文档

答案 1 :(得分:4)

\ Q表示您的正则表达式可以替换为index。对于与案例无关的搜索,$ html和$ tag应尽可能早地转换为小写。

my $htmllc=lc($html);
while () {
  ...
  if (index($htmllc,$tag)>-1) {
   ...
  }
}

P.S。您应该尝试对几种解决方案进行基准测试。