Проблема с утечкой памяти PHP-скрипта
Я запускаю приведенный ниже PHP-код из командной строки. Проблема в том, что его потребление памяти намного больше, чем должно быть. Я не могу, хоть убей, понять, где поглощается память.
for ($i=0;$i<100;$i++)
{
$classObject = $classObjects[$i];
echo $i . " : " . memory_get_usage(true) . "\n";
$classDOM = $scraper->scrapeClassInfo($classObject,$termMap,$subjectMap);
unset($classDOM);
}
По моему мнению, память, потребляемая моим сценарием, должна оставаться более или менее постоянной после каждой итерации цикла. Любая память, потребляемая $scraper->scrapeClassInfo()
, должна быть освобождена, когда ее члены выходят за пределы области действия.
Это выходной файл, который я получаю. Для краткости, Я показываю каждую 10-ю строку вывода:
0 : 5767168
10 : 12058624
20 : 18350080
30 : 24903680
40 : 30932992
50 : 37748736
60 : 43778048
70 : 49807360
80 : 55836672
90 : 62914560
97 : 66846720
Fatal error: Allowed memory size of 67108864 bytes exhausted (tried to allocate 44 bytes) in /home/content/60/8349160/html/drexel/simple_html_dom.php on line 1255
Наконец, насколько я вижу, то, что делает $scraper->scrapeClassInfo()
, на самом деле не должно быть виновником, но на всякий случай вот код:
function scrapeClassInfo($class,$termMap,$subjectMap)
{
$ckfile = tempnam ("/tmp", "CURLCOOKIE");
$ckfile2 = tempnam ("/tmp", "CURLCOOKIE2");
$ckfile3 = tempnam ("/tmp", "CURLCOOKIE3");
$termpage = $termMap[$class['termcode']];
$subjectpage = $subjectMap[$class['subjectcode']];
$classpage = $class['classlink'];
//hit the main page and get cookie
$ch = curl_init();
curl_setopt($ch, CURLOPT_COOKIEJAR, $ckfile);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL, $this->mainURL);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_exec($ch);
curl_close($ch);
//hit the term page and get cookie
$ch = curl_init();
curl_setopt($ch, CURLOPT_COOKIEFILE, $ckfile);
curl_setopt($ch, CURLOPT_COOKIEJAR, $ckfile2);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL, $termpage);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_exec($ch);
curl_close($ch);
//hit the subject page and get cookie
$ch = curl_init();
curl_setopt($ch, CURLOPT_COOKIEJAR, $ckfile3);
curl_setopt($ch, CURLOPT_COOKIEFILE, $ckfile2);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL, $subjectpage);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_exec($ch);
curl_close($ch);
//hit the class page and scrape
$ch = curl_init();
curl_setopt($ch, CURLOPT_COOKIEFILE, $ckfile3);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL, $classpage);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$result = curl_exec($ch);
curl_close($ch);
return str_get_html($result);
}
Метод, вызываемый в последней строке, str_get_html()
является членом Простого синтаксического анализатора HTML DOM
Если это имеет значение, вот как я называю свой скрипт:
/usr/local/php5/bin/php index.php 2>&1 1>output
2 answers
Ладно, разобрался. По-видимому, это ошибка, от которой страдают все версии PHP до 5.3. Установка CURLOPT_RETURNTRANSFER
в true
вызывает массовые утечки памяти.
Я снова запустил скрипт, на этот раз вызвав двоичный файл php 5.3:
/web/cgi-bin/php5_3 index.php 2>&1 1>output
И выходной файл гласит:
0 : 6291456
10 : 9437184
20 : 10747904
30 : 11534336
40 : 11534336
50 : 11534336
60 : 11534336
70 : 11534336
80 : 11534336
90 : 11534336
99 : 11534336
152.74998211861 sec
Вот об этом я и говорю! Идеально постоянный объем памяти.
Я нашел следующее в вашем коде.
- Удалите
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true)
, так как вы его не записываете. - Не закрывайте ручку завитка. Используйте его повторно.
В качестве текущего обходного пути вы можете запустить php-скрипт с более высоким memroy_limit
$ php -d memory_limit=1G /path/to/script
1G означает 1 гигабайт.