【问题标题】:Are preg_match() and preg_replace() slow?preg_match() 和 preg_replace() 慢吗?
【发布时间】:2012-12-29 19:53:06
【问题描述】:

我用 PHP 编码已经有一段时间了,我一直在读到你应该只在必要时使用 preg_matchpreg_replace,因为它会降低性能。为什么是这样?在一个文件中使用 20 preg_matches 而不是使用另一个 PHP 函数真的很糟糕吗?

【问题讨论】:

  • 必须编译正则表达式,解析字符串等等......使用正则表达式没有错,但是很多人通过做preg_match('/foo/', $bar)而不是strpos('foo', $bar) !== false等愚蠢的事情来滥用它们跨度>
  • 答案是:这取决于您想到的“其他 PHP 函数”。有些情况可能更快,有些则不然。此外,速度并不总是最重要的因素。无论速度如何,正则表达式都可能是该工作的最佳工具,或者即使它运行得更快,它也可能是该工作的错误工具。
  • 就我而言,这非常有用,因为我在渲染页面之前使用了大约 30+ preg_replace()。我设法缓存了我的页面,所以我不必总是迭代。

标签: php regex optimization preg-replace preg-match


【解决方案1】:

这真的取决于您的用例。使用正则表达式本身并没有什么“坏处”。有时它是您对特定问题的唯一可用解决方案。但是,有时简单的字符串操作函数也可以正常工作。这些往往比preg* 函数更快,因此,如果您遇到脚本运行非常频繁和/或要执行大量字符串操作的情况,则使用正则表达式的影响可能会开始感受一下。

与任何情况一样,您应该在您的应用程序和环境中进行测试,然后确定最适合您的方法。

【讨论】:

    【解决方案2】:

    取决于你在做什么。对于复杂的正则表达式,只需使用 preg_ 函数,如果您需要简单的替换或类似函数,请使用其他更具体的函数,如 str_replace()、strpos()、strstr()...

    网络上到处都是讨论,比如http://www.simplemachines.org/community/index.php?topic=175031.0

    【讨论】:

      【解决方案3】:

      除非遇到问题,否则不要担心优化。

      如果不使用 XDebug (http://xdebug.org) 等工具进行测量,请勿寻找优化区域。

      如果您的代码使用 preg_match() 运行需要 100 毫秒,而通过其他方法需要 110 毫秒,那么您真的在乎差异吗?

      首先考虑正确性和清晰性,然后考虑速度。

      【讨论】:

      • 虽然我完全同意为了正确性和清晰性而编写代码,但编写优化代码也同样重要。作为定期处理大量网站的人,优化代码与任何事情一样重要。
      • 伙计,我真的可以理解“不衡量就不要优化”的口头禅。我花了一整天的时间减少数据库查询的数量,几乎没有明显的差异。然后使用真正的调试器,我发现一个小的缓存写入占用了将近一秒的加载时间。
      【解决方案4】:

      正如 Mike Brant 在他的回答中所说:使用任何 preg_* 函数都没有错,如果你需要它们。
      您想知道在单个文件中调用 20 个 preg_match 是否是个好主意,好吧,老实说:我会说这太多了。我经常说“如果您对问题的解决方案在任何给定时间依赖于 3 个以上的正则表达式,那么您就是问题的一部分”。不过,我偶尔也会违背自己的咒语。

      如果您正在使用 20 个preg_match 调用,那么您很可能只需仔细查看实际的正则表达式就可以将这个数字减半。正则表达式,尤其是 Perl 正则表达式,非常强大,非常值得花时间去了解它们。 为什么它们往往变慢的原因仅仅是因为必须解析正则表达式,并在某个低级别“翻译”为相当数量的分支和循环。例如,如果您想用大写字符替换所有小写的a,当然可以使用正则表达式,但在 PHP 中会如下所示:

      preg_replace('/a/','A',$string);
      

      查看表达式,第一个参数:它是作为参数传递的字符串。这个字符串将被解析(解析时,检查分隔符,创建匹配字符串,然后迭代字符串,将每个字符与模式(在本例中为a)进行比较,以及 if 子字符串匹配,它被替换。
      看起来有点麻烦,特别是考虑到最后一步(比较子字符串和替换匹配)是我们真正想要的。

      $string = str_replace('a','A',$string);
      

      仅此而已,无需在解析和验证正则表达式时执行额外检查。
      不要忘记preg_match 也构造了一个匹配数组,构造一个数组也不是免费的。

      简而言之:正则表达式的速度较慢,因为表达式被解析、验证并最终转换为一组简单的低级指令。

      请注意,在某些情况下,人们使用 explodeimplode 进行字符串操作。这也创建了一个 - 再次 - 不是免费的数组。考虑到您在此后不久就内爆了相同的数组。也许另一种选择更可取(在某些情况下preg_replace 可以在这里更快)。
      基本上:正则表达式需要额外的处理,简单的字符串函数不需要。但是如果有疑问,只有一种方法可以绝对确定:设置测试脚本...

      【讨论】:

        【解决方案5】:

        检查需要多少时间(显示STARTEDENDED的时间):

        var_dump( microtime(true) );
        
        //...............  your function executions here.............
        
        var_dump( microtime(true) );
        

        【讨论】:

          【解决方案6】:

          短字符串(如小于几千字节)的性能差异可以忽略不计。对于长字符串,例如超过 30-50 kB(通常是所见即所得内容)的性能差异变得更加显着,特别是对于贪婪的变体 - 例如preg_match_all。因此,对于长字符串,使用简单的字符串迭代/查找通常会更快,例如由str_pos() 提取或用substr() 替换部分字符串,然后仅应用 preg_* 函数 - 用于提取的短字符串。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-04-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-07-11
            相关资源
            最近更新 更多