出于某种原因,即使没有使用多字节字符,只需将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";
结果是:
u Modifier: 2.5037050247192E-5
No Modifier: 2.4969577789307E-6
我试着看看这是否是一个已知的在线错误,但supposedly, it is not a problem with PHP。
这是什么原因导致匹配 1 的最佳方法更快?
1 &#34;匹配&#34;是指任何比赛。使用的示例只是一个最小的示例,显然可以以更好的方式进行匹配。
答案 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
选项。
无论如何,你的基准测试应该经历更多迭代才有意义。您应该测量几秒钟的计算时间,以更好地了解此功能的影响。