我的网站目前使用模板系统,该系统会加载.tpl
个文件列表,并用正确的内容替换{bracelet}
,并在页面上输出。
我需要获取所有模板中所有手镯的列表,以便我可以阻止PHP运行特定于手镯的代码,这将有助于减少查询量。
目前我的页面加载时间为1.09秒,如果我添加以下代码,则页面加载时间会增加到1.53秒。
我收集这是因为我将100个左右的文件加载到内存中,然后加载到preg_match_all
并将它们全部推入一个数组?
bracelets = [];
foreach($files as $file) {
if (empty($file)) continue;
$html = get_file_contents($file);
$matches = [];
preg_match_all("/{(.*?)\}/", $html, $matches);
bracelets = (array_merge($bracelets, $matches[1]));
}
bracelets = array_unique(bracelets);
导致速度降低的代码是什么?
答案 0 :(得分:1)
使用长度未知的文件时,基于懒点的模式可能会降低性能。如果在定界符之间出现大块文本(在这里为大括号),则会发生这种情况,因为{.*?}
的工作方式如下:{
被匹配,然后.*?
被跳过,{{1}搜寻。如果不存在,则使用}
来匹配.*?
之后的字符,并测试下一个字符是否为{
。在找到}
之前,此过程重复的次数与}
以外的其他字符相同。这意味着引擎仍然花费太多时间才能到达关闭定界符。
在使用}
否定字符类时,您可以使用贪婪的[^}]
或*
量词,因为您不再需要单独测试所有字符,因此引擎会贪婪地捕获所有1 /一次包含+
以外的0个或更多字符,并达到}
(如果有)。\
由于您需要匹配}
之类的值并避免返回类似条目的{bracelet}
,因此您当前的正则表达式不仅速度慢,而且是错误的。
替换为
{brace let}
"/{([^{}\s]+)}/"
部分匹配[^{}\s]+
,{
和空格以外的1个或多个字符。
关于串联仅保留唯一值的数组,请参见Fastest way to combine thousands of arrays uniquely in PHP。