PHP сборка мусора отстой или это только у меня так? - PullRequest
7 голосов
/ 01 августа 2010

У меня есть функция, ниже которой я очень часто вызываю в цикле.

Я ждал 5 минут, когда объем памяти вырос с 1 МБ до 156 МБ.Разве PHP-сборщик мусора не должен включаться и уменьшать это в какой-то момент?!

Это потому, что я установил лимит памяти в 256 МБ?использование памяти.В точке 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 />';

}

Как видите, я попытался использовать unset слабо.Хотя это не очень хорошо, насколько я понимаю, память не «сбрасывает» память, как только я ее называю.

Спасибо всем за помощь в том, как я могу уменьшить этот восходящий рост памяти.

Ответы [ 3 ]

8 голосов
/ 01 августа 2010

Существует известная утечка памяти с помощью file_get_html (): http://simplehtmldom.sourceforge.net/manual_faq.htm#memory_leak

Решение состоит в том, чтобы использовать

$html->clear();

Что вы делаете, НО: вы используете оба $ htmlвнутри и снаружи петли.Внутри цикла вы вызываете $ html-> clear (), а затем снова в конце вашей функции $ html-> clear () (я предполагаю, что вы поймаете исходную ссылку на объект file_get_html ()).Последний звонок ничего не делает.Вы теряете память при первом вызове $html = file_get_html().

Попробуйте использовать другую переменную ($ html1, может быть?) В вашем цикле и посмотрите, что произойдет.

3 голосов
/ 01 августа 2010

Целью сборщика мусора является исключительно перехват круглых ссылок.

Если их нет, переменные немедленно удаляются, когда их счетчик ссылок достигает 0.

Я не рекомендую использовать unset, за исключением исключительных случаев. Вместо этого используйте функции и полагайтесь на переменные, чтобы выйти из области видимости и восстановить память.

Кроме этого, мы не можем описать вам, что именно происходит, потому что нам нужно точно знать, что делает простой парсер DOM. Возможно, существуют циклические ссылки или глобальные ресурсы, содержащие ссылку, но это будет трудно узнать.

См. основы подсчета ссылок и циклы сбора .

2 голосов
/ 03 августа 2010

В PHP не было надлежащего сборщика мусора до 5,3 .В основном он использовал только подсчет ссылок, который оставлял бы циклические ссылки на месте, пока скрипт не завершился (например, $a =& $a является циклическим).Кроме того, код очистки, который он имел, выполнялся, только если этого требовала нагрузка на память.например, нет смысла делать дорогостоящий цикл очистки, если только что освободившаяся память не была нужна.

Начиная с 5.3, есть надлежащий сборщик мусора, и вы можете заставить его работать с gc_enable() и gc_collect_cycles().

...