PHP& do / while循环内存泄漏

时间:2010-07-09 07:49:20

标签: php mysql loops

我有一个遍历数据库行的do / while循环。因为它在处理100000行时运行了很多天,所以内存消耗对于保持检查很重要,否则会崩溃。现在每次迭代都会增加大约4kb的脚本内存使用量。我正在使用memory_get_usage()来监控使用情况。

我在每次迭代中首先取消了循环中使用的每个变量,所以我真的不知道我还能做什么。我的猜测是,每次迭代时都会收集一些数据,这就是消耗4kb的内存。我知道4kb听起来并不多,但是当你有100000次迭代时很快就会加起来。

有人可以建议另一种方法来浏览大量的数据库行,或者如何以某种方式消除这种“内存泄漏”?

修改的 这是UPDATED循环代码。上面只有几个require_once()s。

$URLs = new URLs_url(db());
$c = new Curl;
$c->headers = 1;
$c->timeout = 60;
$c->getinfo = true;
$c->follow = 0;
$c->save_cookies = false;

do {
    // Get url that hasn't been checked for a week
    $urls = null;

    // Check week old
    $urls = $URLs->all($where)->limit(10);

    foreach($urls as $url) {
        #echo date("d/m/Y h:i").' | Checking '.$url->url.' | db http_code: '.$url->http_code;

        // Get http code    
        $c->url = $url->url;
        $data = $c->get();

        #echo ' - new http_code: '.$data['http_code'];

        // Save info
        $url->http_code = $data['http_code'];
        $url->lastchecked = time();
        $URLs->save($url);
        $url = null;
        #unset($c);
        $data = null;
        #echo "\n".memory_get_usage().' | ';
        echo "\nInner loop memory usage: ".memory_get_usage();
    }
    echo "\nOuter loop memory usage: ".memory_get_usage();

} while($urls);

一些记录两个循环中内存消耗的行为:

Inner loop memory usage: 611080
Inner loop memory usage: 612452
Inner loop memory usage: 613788
Inner loop memory usage: 615124
Inner loop memory usage: 616460
Inner loop memory usage: 617796
Inner loop memory usage: 619132
Inner loop memory usage: 620500
Inner loop memory usage: 621836
Inner loop memory usage: 623172
Outer loop memory usage: 545240
Inner loop memory usage: 630680
Inner loop memory usage: 632016
Inner loop memory usage: 633352
Inner loop memory usage: 634688
Inner loop memory usage: 636088
Inner loop memory usage: 637424
Inner loop memory usage: 638760
Inner loop memory usage: 640096
Inner loop memory usage: 641432
Inner loop memory usage: 642768
Outer loop memory usage: 556392
Inner loop memory usage: 640416
Inner loop memory usage: 641752
Inner loop memory usage: 643088
Inner loop memory usage: 644424
Inner loop memory usage: 645760
Inner loop memory usage: 647096
Inner loop memory usage: 648432
Inner loop memory usage: 649768
Inner loop memory usage: 651104
Inner loop memory usage: 652568
Outer loop memory usage: 567608
Inner loop memory usage: 645924
Inner loop memory usage: 647260
Inner loop memory usage: 648596
Inner loop memory usage: 649932
Inner loop memory usage: 651268
Inner loop memory usage: 652604
Inner loop memory usage: 653940
Inner loop memory usage: 655276
Inner loop memory usage: 656624
Inner loop memory usage: 657960
Outer loop memory usage: 578732

4 个答案:

答案 0 :(得分:2)

这个位应该只在循环之前发生一次:

$c = new Curl;
$c->headers = 1;
$c->timeout = 60;
...
$c->getinfo = true;
$c->follow = 0;
$c->save_cookies = false;

编辑:哦,整个事情都包含在do / while循环中。 /捂脸

编辑2:还有这个重要的一点:

  

unset($ class_object)不会释放   对象分配的资源。如果   用于循环,创建和   摧毁对象,这可能很容易   导致资源问题。明确地   调用析构函数来绕过析构函数   问题

http://www.php.net/manual/en/function.unset.php#98692

编辑3:

这是什么?不能以某种方式将其移到循环之外吗?

$URLs = new URLs_url(db());

编辑4:

暂时尝试删除这些行。

    $url->http_code = $data['http_code'];
    $url->lastchecked = time();
    $URLs->save($url);

答案 1 :(得分:0)

我认为你的核心问题是你只是在外循环中清理东西。

例如,

$c = new Curl将为内循环的每次迭代分配内存到堆,但是你只是unset最后一个实例。我会在内循环的 end unset你可以做任何事情($c$data

答案 2 :(得分:0)

问题可能是

$c = new Curl

是否可以在循环外部实例化Curl,然后在内部继续重用相同的实例。如果需要,可以在循环中将所有字段重置为null。

我有类似的问题。取消设置无效 - 事实证明垃圾收集是垃圾。当我重用对象时,它很好(好吧,它因各种原因而破坏,所以我最终在Java中重新实现)。

答案 3 :(得分:0)

这可能会或可能不会对你有所帮助,但回到2000年时,我有一个客户,他的互联网真的很慢,并希望在本地完成他所有的网站cms更新,并在完成后更新为live。当时在win xp上的IIS上,我找不到从60秒增加脚本超时的方法,并且通常需要2分钟才能完成更新,因此显然会超时。

要解决这个问题,我会让脚本更新一定数量的行,这些行保证在一分钟内安全执行,然后使用参数从哪里继续调用,依此类推,直到所有行都更新为止。也许你可以尝试类似的情况吗?

也许在调用之前运行它一段时间,或者在你的情况下,可能检查内存,并在使用率过高时重定向?

我使用过这样的东西:

脚本顶部:

$started = microtime(true);

然后在你的循环中:

if((microtime(true)-$started) > ($seconds_to_redirect)) {
    //call script with parameter
}

这是我能想到的全部。