PCRE_UTF8修改器非常慢

时间:2015-03-11 23:43:53

标签: php regex utf-8 pcre

出于某种原因,即使没有使用多字节字符,只需将PCRE_UTF8修饰符添加到preg_match()的正则表达式输入中,即可大大减少(x10)执行时间。我无法弄清楚为什么会这样,以及如何最好地缩短时间。用于测试的脚本是:

$s = microtime(true);
for ($i = 0; $i < 1000; $i++) {
    preg_match('/ /u', str_repeat(' ', 50000), $match);
}
$e = microtime(true);
echo "u Modifier:\t".(($e-$s)/$i)."\n";
$s = microtime(true);
for ($i = 0; $i < 1000; $i++) {
    preg_match('/ /', str_repeat(' ', 50000), $match);
}
$e = microtime(true);
echo "No Modifier:\t".(($e-$s)/$i)."\n";

Try it online here.

结果是:

u Modifier: 2.5037050247192E-5
No Modifier:    2.4969577789307E-6

我试着看看这是否是一个已知的在线错误,但supposedly, it is not a problem with PHP

这是什么原因导致匹配 1 的最佳方法更快?


1 &#34;匹配&#34;是指任何比赛。使用的示例只是一个最小的示例,显然可以以更好的方式进行匹配。

1 个答案:

答案 0 :(得分:3)

PCRE在进行任何其他处理之前检查UTF有效性。

来自PCRE docs

  

设置PCRE2_UTF选项后,在进入相关功能时,作为模式和主题传递的字符串(默认情况下)会检查其有效性。如果传递了无效的UTF字符串,则返回负的错误代码。可以通过调用pcre2_get_startchar()从匹配数据块中提取与违规字符相对的代码单元,这在UTF错误之后用于此目的。

     

...

     

在进行任何其他处理之前检查整个字符串。除了检查字符串的格式外,还要检查以确保所有代码点都位于U + 0到的范围内U + 10FFFF,不包括代理区域。不排除所谓的“非字符”代码点,因为Unicode更正#9明确表明它们不应该是。

     

...

     

在某些情况下,您可能已经知道您的字符串是有效的,因此希望跳过这些检查以提高性能,例如,在长主题字符串的情况下反复扫描。如果在编译时或匹配时设置 PCRE2_NO_UTF_CHECK选项,则PCRE2假定它(分别)给出的模式或主题仅包含有效的UTF代码单元序列。

(注意:这些文档引自PCRE2,但PCRE行为是相同的)

不幸的是,我认为没有办法从PHP设置PCRE2_NO_UTF_CHECK选项。

无论如何,你的基准测试应该经历更多迭代才有意义。您应该测量几秒钟的计算时间,以更好地了解此功能的影响。