我有一个循环,它在每次迭代中占用大量文本,并用一些其他内容替换特定的占位符('token'):
$string = $pageContent;
foreach($categories as $row) {
$images = $mdlGallery->getByCategory($row['id']);
if (!empty($images)) {
$plug = Plugin::get('includes/gallery', array('rows' => $images));
$string = str_replace($row['token'], $plug, $string);
}
}
Plugin类和它的get()方法只从特定目录中获取正确的文件,并将缓冲区作为字符串输出。
可能存在大量类别因此我想知道在使用strpos()函数填充来自给定类别的所有图像之前,首先检查输入字符串是否出现特定“令牌”是否更好像这样:
foreach($categories as $row) {
if (strpos($string, $row['token']) !== false) {
$images = $mdlGallery->getByCategory($row['id']);
if (!empty($images)) {
$plug = Plugin::get('includes/gallery', array('rows' => $images));
$string = str_replace($row['token'], $plug, $string);
}
}
}
我担心的是表现 - 这会有帮助吗? - 考虑$ string可能包含大量字符(MySQL中的TEXT字段类型)?
答案 0 :(得分:4)
根据您的示例代码,Plugin::get()
中使用的文件似乎很小,这意味着包含它们或阅读它们不会产生很大的性能成本,但如果有很多这些文件,您可能需要考虑因OS排队机制导致的成本,即使它们包含的数据不大。
getByCategory
方法应该会产生很大的性能成本,因为它意味着许多连接 - >查询 - >> read->关闭到数据库的通信序列,每个都意味着传输大量数据(您提到的TEXT
个字段。
您应该考虑使用单个SQL查询将数据作为批处理操作提取,并将其存储在由行ID索引的缓存变量中,以便getByCategory
可以从缓存中获取它。
您当前的问题不是简单的代码审查,而是一个方法问题。您已经将小型数据集的典型技术用作处理大型数据集的方法。如果您有中等数据集并且感觉不到性能衰减,那么“将foreach包装在简单脚本上”的概念就有效,如果您不需要单独的方法来处理大型数据集。
使用strpos
意味着在整个干草堆中运行一次以检查它是否包含针头,然后再次通过它再次使用str_replace
进行替换。
如果干草堆不包含针,strpos === str_replace
(在计算复杂性方面),因为它们都必须穿过整个字符串直到最后才能确保没有针。
对于任何不包含针头的干草堆而言,使用这两种功能会增加100%的计算复杂度,并且对于包含针头的任何干草堆而言,计算复杂性会增加1%到100%,因为strpos
在找到第一根针后会立即返回,这可以在弦的开头,中间或末尾找到。
简而言之不要使用strpos
它对您没有帮助,如果您使用preg_replace
,则RegEx引擎可能会产生比{{1}更多的计算复杂性对于不包含针头的干草堆。
答案 1 :(得分:0)
感谢Mihai - 这很有意义 - 但是在这个特殊场景中,即使我首先从数据库中获取所有记录 - 意味着所有具有相关类别的图像 - $ string会很少包含的不仅仅是一两个令牌' - 意味着如果有许多类别('令牌')进行比较,使用strpos()实际上可以节省时间。
想象一下,我们不会在每次迭代中调用 getByCategory ,因为我们已经将所有可能的记录存储在早期生成的数组中 - 我们仍然需要在Plugin :: get中进行输出缓冲()方法和str_replace() - 意思是如果我们说20个类别 - 这将发生20次而不一定是'令牌'包含在$ string中。
因此,如果假设有大量的“令牌”,那么您的建议就会奏效。在$ string中找到的比较我们正在循环的类别数量,但是对于少量的标记'我认为strpos()仍然是有益的,因为这将是每个类别执行的唯一一个而不是当strpos()返回true时跟随两个 - 在这种情况下它是以strpos形式支付的小代价()每次在循环中比较ob和str_replace - 你认为不是吗?
我非常感谢你的解释。
答案 2 :(得分:0)
如果您正在寻找优化(尤其是微优化),我认为最好自己进行基准测试。任何实现都有一个变体(通常),因此最好对您使用的变体进行基准测试。根据这个,你可以在这里看到基准测试结果: 使用strpos:http://3v4l.org/pb4hY#v533 没有strpos:http://3v4l.org/v35gT