【问题标题】:Parse many small strings or a single big string - which is faster?解析许多小字符串或单个大字符串 - 哪个更快?
【发布时间】:2012-12-24 03:52:05
【问题描述】:

在需要用正则表达式解析大量字符串的场景下,考虑到所有测试都使用同一个RegEx针,这样会更快:

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

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

基准测试


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

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

26853 个交互在 5 秒内完成单个大字符串测试

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

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

preg_grep()

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

【问题讨论】:

  • 必须编译正则表达式。除非您正在编写一些丑陋的长正则表达式,否则编译开销就是您的时间差异的来源。
  • @MarcB 我不明白。当我为数组中的每个字符串调用 RegEx 函数时,编译开销应该比第二种方法大,但速度要快 5 倍。
  • 啊。对不起。向后阅读您的结果,认为它们是时间等价的(例如,26853 比 122185 短)。但是,如果您正在处理一个数组,则不要在循环中使用 preg_match 。 preg_grep 用于处理数组中的匹配。也许现在是串联开销杀死性能。尝试预先构建整体字符串,然后进行测试。
  • 问题可能是内存。为超级字符串分配大量空间可能会减慢您的系统速度,但我不确定字符串有多大或在任何一种情况下您实际上如何加载字符串。
  • 如果您有兴趣,我已经在我的帖子中提供了源代码 - pastebin.com/znW5jYY9 基准测试不太可能使我的计算机超载。我还确保我有一个相当优化的代码。解析多个字符串确实比一个大字符串要快。

标签: regex performance


【解决方案1】:

您的基准测试存在缺陷。看看你的这段代码:

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()。此外,在某个地方需要将大字符串转换为数组,这也需要时间。

【讨论】:

  • 这很奇怪......在我看来,我的代码与您的代码基本相同。并排看,我真的说不出任何本质上的不同。 pastebin.com/uQ0kS6G3(改编)我仍然得到数组方法比内爆字符串方法快很多倍。
  • @caiosm1005 使用 pcre 的结果往往会在较大的字符串上变慢,这可能解释了一些事情。尽管如此,此时 grep 选项可能是最好的选择。
  • 但它与您的代码中的字符串相同。为什么结果相反?
  • @caiosm1005 仍然不是相同的代码......检查我更新的答案。
  • 糟糕!你是对的,我的错误;)我稍后会更新我的答案
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 2015-10-16
    • 2020-05-25
    • 2011-10-10
    • 1970-01-01
    • 2012-01-06
    • 2016-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多