Я запускаю код 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()
должна быть освобождена, когда ее члены выходят из области видимости.
Это выходной файл, который я получаю. Для краткости я показываю каждую десятую строку вывода:
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()
, то, что $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()
является членом Simple HTML DOM Parser
Если это имеет значение, так я называю свой сценарий:
/usr/local/php5/bin/php index.php 2>&1 1>output
Хорошо, понял. По-видимому, это ошибка, от которой страдает вся версия 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 гигабайт.