3

在必须使用正则表达式解析大量字符串的场景中,考虑到所有测试都使用相同的 RegEx 指针,这样会更快:

  1. 单独测试数组中的每个字符串,或者;
  2. 将所有内容连接成一个大字符串并只测试一次?

我相信数字 2 最好,而不是多次启动 RegEx 引擎来处理字符串数组。然而,在 PHP (PCRE) 中进行了一些测试后,这似乎是不真实的。

基准


我在 PHP 5.3 (源代码)中做了一个简单的基准测试,得到了以下结果:

122185 次交互在 5 秒内测试数组中的多个较小字符串

5 秒内完成26853 次交互,进行单个大字符串测试

因此,我必须得出结论,第一种方法最多快 5 倍。但是,我想要求一个权威的答案来确认这一点;由于一些我不知道的 PHP 优化,我可能会错误地假设事情。

在使用正则表达式测试大字符串之前,是否总是一个更优化的解决方案,而不是专门在 PCRE 中?

preg_grep()

我认为这里不应该考虑这个功能。这是一个基准测试,而不是优化问题。更不用说该函数是特定于 PHP 的方法。此外,preg_match_all返回所有匹配的子字符串,而preg_grep仅指示匹配的数组元素。

4

2 回答 2

3

你的基准有缺陷。看看你的这段代码:

while(time() - $TimeStart < 5)
    for($i = 0; $i < $Length; $i++, $Iterations++)
    {
        preg_match_all($RegEx, $Input[$i], $m);
    }
}

$Iterations应该增加在里面,而while不是里面for。将前一个结果除以:

24437 iterations using array
26853 iterations using big string

您不应该time()用于时间测量,microtime()更适合获得准确性。

最后,这个基准测试并不完整,因为要为两个测试获得相同的结果,数组方法需要array_merge()在每次迭代后执行。此外,在某个地方需要将大字符串转换为数组,这也需要时间。

于 2012-12-24T05:32:00.740 回答
1

您绝对不应该所有目标字符串合并为一个。一方面,它会破坏很多在较短字符串上可以正常工作的正则表达式。^$\A和等锚点\z会突然发现自己没有可匹配的对象。此外,严重依赖诸如.* or.*?` 之类的正则表达式,尽管其固有的低效率,但在较短的字符串上工作,当在 Frankenstring 上使用时往往会变得非常缓慢

但即使连接版本更快,这有关系吗?有没有试过阵列版,发现太慢了?这是一个非常激进的解决方案(如果是解决方案);如果我是你,我会推迟实施它,直到我有它可以解决的问题。

于 2012-12-24T10:49:23.913 回答