1

我有一个循环,它在每次迭代中需要大量文本,并用其他一些内容替换特定的占位符('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 字段类型)?

4

3 回答 3

4

解决您的问题

根据您的示例代码,其中使用的文件似乎Plugin::get()很小,这意味着包含它们或读取它们不应该产生很大的性能成本,但如果它们很多,您可能需要考虑由于操作系统排队机制而产生的这些成本即使它们包含的数据不大。

getByCategory方法应该会产生很大的性能成本,因为它意味着与数据库的许多连接->查询->读取->关闭通信序列,并且每个都意味着传输大量数据(TEXT您提到的字段)。

您应该考虑使用单个 SQL 查询以批处理操作的形式获取数据,并将其存储在由行 id 索引的缓存变量中,以便getByCategory可以从缓存中获取数据。

您当前的问题不是简单的代码审查问题,而是方法问题。您已经使用了针对小型数据集的典型技术作为处理大型数据集的方法。如果您拥有中等数据集并且没有感觉到性能下降,则“在简单脚本上包装 foreach”的概念有效,如果您不需要单独的方法来处理大型数据集。

回答你的问题

usingstrpos意味着遍历整个 haystack 一次以检查它是否包含针,然后再次遍历它以进行替换str_replace

如果干草堆不包含针,strpos === str_replace(在计算复杂性方面)因为它们都必须遍历整个字符串直到最后以确保没有针。

使用这两个函数会为任何不包含针的干草堆增加 100% 的计算复杂度,并为任何包含针的干草堆增加 1% 到 100% 的计算复杂度,因为strpos将在找到第一根针后立即返回可以在字符串的开头、中间或结尾找到。

简而言之,在这里不要使用strpos它对您没有帮助,如果您使用的是 RegEx 引擎,则可能会比不包含针头的干草堆preg_replace产生更多的计算复杂性。strpos

于 2012-07-17T11:07:33.520 回答
0

谢谢 Mihai - 这很有意义,但是 - 在这种特殊情况下,即使我首先从数据库中获取所有记录 - 意味着所有具有相关类别的图像 - $string 很少会包含超过只有一两个“令牌”——这意味着如果有许多类别(“令牌”)可以比较,使用 strpos() 实际上可以节省时间。

想象一下,我们没有在每次迭代中调用getByCategory,因为我们已经将所有可能的记录存储在之前生成的数组中——我们仍然必须通过 Plugin::get() 方法和 str_replace() 内部的输出缓冲——这意味着如果我们说 20 个类别 - 这将发生 20 次,而 $string 中不一定包含“令牌”。

因此,如果假设在 $string 中发现大量“令牌”与我们循环遍历的类别数量相比,您的建议将起作用,但对于少数“令牌”,我认为 strpos() 会仍然是有益的,因为这将是每个类别中唯一执行的一个,而不是当 strpos() 返回 true 时执行的两个 - 在这种情况下,与 ob 和 str_replace 相比,每次都以 strpos() 的形式支付的代价很小在循环中 - 你不觉得吗?

我非常感谢你的解释。

于 2012-07-17T11:45:44.827 回答
0

如果您正在寻找优化(尤其是微优化),我认为最好自己对东西进行基准测试。任何实现都有不止一个变体(通常),因此最好对您使用的变体进行基准测试。据此,您可以在这里看到基准测试结果:使用 strpos:http: //3v4l.org/pb4hY#v533 没有 strpos:http: //3v4l.org/v35gT

于 2014-04-28T12:11:06.547 回答