【发布时间】:2014-06-10 11:45:36
【问题描述】:
冒着被重定向到this answer 的风险(是的,我读了它并花了最后 5 分钟大声笑),请允许我解释一下这个问题,这只是众多问题中的一个。
我的雇主要求我审查一个用 PHP 编写的网站,使用 Smarty 作为模板,使用 MySQL 作为 DBMS。它目前运行非常缓慢,最多需要 2 分钟(完全白屏,不少于)才能完全加载。
使用 xdebug 分析代码,我发现一个 preg_replace 调用大约需要 30 秒才能完成,该调用当前遍历所有 HTML 代码并将找到的每个 URL 替换为其 SEO 友好版本。完成后,它将所有代码输出到浏览器。 (正如我之前所说,这不是唯一的问题 - 代码相当旧,它显示了 - 但我将专注于这个问题。)
进一步深入研究代码,我发现它当前查看了 1702 个模式,每个匹配项都匹配(大小相等的数组中的匹配和替换),这肯定会考虑到它所花费的时间。
代码如下:
//This is just a call to a MySQL query which gets the relevant SEO-friendly URLs:
$seourls_data = $oSeoShared->getSeourls();
$url_masks = array();
$seourls = array();
foreach ($seourls_data as $seourl_data)
{
if ($seourl_data["url"])
{
$url_masks[] = "/([\"'\>\s]{1})".$site.str_replace("/", "\/", $seourl_data["url"])."([\#|\"'\s]{1})/";
$seourls[] = "$1".MAINSITE_URL.$seourl_data["seourl"]."$2";
}
}
//After filling both $url_masks and $seourls arrays, then the HTML is parsed:
$html_seo = preg_replace($url_masks, $seourls, $html);
//After it completes, $html_seo is simply echo'ed to the browser.
现在,我知道问题的明显答案是:不要使用正则表达式解析 HTML。但是,如何解决这个特定问题呢?我的第一次尝试可能是:
- 将(希望是格式良好的)HTML 加载到 DOMDocument 中,然后在每个 a 标签中获取每个 href 属性,like so.
- 遍历每个节点,替换为适当匹配找到的 URL(这可能意味着无论如何都要使用以前的正则表达式,但在一个大大减小的字符串上)
- ???
- 利润?
但我认为这很可能不是解决问题的正确方法。 有什么想法或建议吗?
谢谢。
【问题讨论】:
-
我想说,不要把坏的 url 放在 html 开头,把好的。而不是这种非常缓慢的方式。
-
目前,该网站无法使用。所以,我要做的第一件事是在数据库中创建一个新列,将过滤内容移至离线进程,并将结果记录在新列中。然后该网站至少可以工作,您可以着手修复实施。
-
that's not the only issue -the code is rather old, and it shows,到时候重写。不幸的是,没有快速的方法来做您想做的事,除非您修复内容中的 url,否则 regex-ing 1702 模式有点令人担忧。 -
感谢所有 cmets(对于冗长的帖子感到抱歉,只是想我会尽可能清楚地说明。)是的,正在进行完整的网站重写(使用 Erlang/ChicagoBoss相反)但由于它不会很快准备好,所以旧网站暂时上线了。不幸的是,让网站处于工作状态太费力了,所以我的雇主告诉我不要管它。了解如何(不)编码的好机会,thougn。
-
也许函数被优化了,你确定执行正则表达式所花费的时间吗?