PHP垃圾收集很糟糕还是仅仅是我?

时间:2010-08-01 17:57:50

标签: php memory garbage-collection

我有一个下面的函数,我经常在循环中调用它。

随着内存从1MB上升到156MB,我等了5分钟。 PHP的garabage收集器不应该在某个时候出现并减少它吗?!

是因为我将内存限制设置为256MB?

在回波点2,3,4,它的内存使用量相当不变。它在第4点下降了半个兆位。但是第1点是主内存增加发生的地方。可能是因为file_get_html将html文件加载到内存中。

我虽然变量$html的明确和未设置会解决这个问题吗?

function get_stuff($link, $category ){

    $html = file_get_html(trim("$link"));

    $article = $html->find('div[class=searchresultsWidget]', 0);

    echo '1 - > '.convert(memory_get_usage(true)).'<br />';  

    foreach($article->find('h4 a') as $link){

        $next_url = 'http://new.mysite.com'.$link->href;

        $font_name = trim($link->plaintext);        

        $html = file_get_html(trim("$next_url"));

        $article = $html->find('form[class=addtags]', 0);

        $font_tags = '';

        foreach($article->find('ul[class=everyone_tags] li a span') as $link){

            $font_tags .= trim($link->innertext).',';   

        }

        echo '2 - > '.convert(memory_get_usage(true)).'<br />'; 

        $font_name = mysql_real_escape_string($font_name);
        $category =  mysql_real_escape_string($category);  
        $font_tags = mysql_real_escape_string($font_tags);  

        $sql = "INSERT INTO tag_data (font_name, category, tags) VALUES ('$font_name', '$category', '$font_tags')";

        unset($font_tags);
        unset($font_name);
        unset($category); 

        $html->clear();   

        mysql_query($sql); 

        unset($sql);   

        echo '3 - > '.convert(memory_get_usage(true)).'<br />';    

} 

    unset($next_url);
    unset($link);
    $html->clear(); 
    unset($html);   
    unset($article);

    echo '4 - > '.convert(memory_get_usage(true)).'<br />';

}

正如你所看到的,我试图无力地利用未设置的东西。虽然它并不好,因为我理解它不会在我打电话时“取消”记忆。

感谢大家帮助我如何减少记忆力的上升。

3 个答案:

答案 0 :(得分:8)

file_get_html()有一个已知的内存泄漏:http://simplehtmldom.sourceforge.net/manual_faq.htm#memory_leak

解决方案是使用

$html->clear();

你在做什么,但是:你在循环的内部和外部使用$ html。在循环内部,您调用$ html-&gt; clear(),然后在函数结束时再接近$ html-&gt; clear()(我假设抓住您的初始file_get_html()对象引用)。最后一次通话没有做任何事情。你正在通过最初的$html = file_get_html()电话泄漏记忆。

尝试在循环中使用另一个变量($ html1,可能?),看看会发生什么。

答案 1 :(得分:3)

垃圾收集器的目的仅仅是捕获循环引用。

如果没有,则一旦参考计数达到0,变量就会立即消除。

除特殊情况外,我不建议您使用unset。使用函数代替并依赖变量超出范围以回收内存。

除此之外,我们无法向您描述究竟是什么,因为我们必须确切地知道简单的DOM解析器正在做什么。可能存在循环引用或持有引用的全局资源,但是很难知道。

请参阅reference counting basicscollecting cycles

答案 2 :(得分:2)

PHP没有合适的垃圾收集器until 5.3。它基本上只使用引用计数,这将留下循环引用,直到脚本终止(例如$a =& $a为循环)。同样,DID所具有的清理代码只有在内存压力要求时才会运行。例如如果不需要新释放的内存,则无需进行昂贵的清理周期。

从5.3开始,有一个合适的垃圾收集器,您可以强制它与gc_enable()gc_collect_cycles()一起运行。