PHP foreach超出了内存限制

时间:2012-04-24 15:00:36

标签: php memory memory-leaks

我试图通过数组中的数千个项目进行操作,执行一些操作并将一些值保存到mysql表中。

然而,当我循环时,内存使用量会不断增长,直到我们用尽我在php.ini中指定的内存为止,这很快。

我尝试使用unset,将变量设置为null并查看垃圾收集,但没有任何影响。

是否有更有效的方法可以遍历这些元素(即内存使用量不会持续增长)。

下面是我正在做的一个简化示例。

foreach ($subscribers as $subscriber)
{
    $member = new Member($subscriber['id']);
    if ($member['id'] > 0)
    {
        $bulletin = Bulletin::getCustomBulletin($member['id']);

        Bulletin::compileBulletin($member['email'], time(), $bulletin['title'], $bulletin['content']);

        echo $member['email'] . "\n";
        echo memory_get_usage() . "\n";
    }
}

这会产生以下结果:

an@email.com
11336688
an@email.com
12043640
an@email.com
12749952

3 个答案:

答案 0 :(得分:1)

$suscribers是否是数据库查询的结果?

如果是这样,它可能是您的问题的根源:即使您一次通过一行,行也将被缓存在内存中。

您可以尝试使用unbuffered queries或限制查询的结果数量,并执行几个较小的查询。

另请参阅:Why "Allowed memory size exhausted"?

答案 1 :(得分:0)

没有任何关于你的foreach循环的怀疑(没有变量未被设置,因为它们都是在每次迭代时被写入的)。您将需要找出导致内存抓取的行。在专业IDE中找到的分析器可以帮助解决这个问题。如果您没有访问权限,则需要像以前一样使用memory_get_usage(),但要在每行之后使用它来检查哪一行导致了瓶颈。

还有免费的分析工具,例如xdebug

答案 2 :(得分:0)

不幸的是,很难从代码中判断出你发布的内容,因为内部没有关于Member对象做什么的线索,但这看起来是可能的:

recursive references leak memory

我会在上面的代码中消除新成员对象的创建,以检查是否是内存泄漏的来源。从你所说的,无论如何创建成员对象可能是不必要的,它可以用静态查找成员函数替换。