Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: phpQuery. Проблема с памятью

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (1): [1]   

> Описание: phpQuery. Проблема с памятью
mikka
Отправлено: 26 Мая, 2019 - 14:35:06
Post Id


Новичок


Покинул форум
Сообщений всего: 12
Дата рег-ции: Окт. 2018  


Помог: 0 раз(а)




Добрый день!

Есть функция, которая, используя библиотеку phpQuery, парсит данные со страницы на сайте. Данные на странице обновляются регулярно, поэтому функция вызывается в цикле приблизительно каждые 5-10 секунд (в зависимости от скорости получения страницы). После продолжительной работы скрипта (приблизительно 8-10 часов, при этом ~3-5 часов из этого времени ноутбук я не трогал), получаю ошибку (забыл ее скопировать с логов), что не хватает памяти для работы phpQuery. В php.ini memory_limit = 1536M. Скрипт работает на локальном сервере (OpenServer). В диспетчере задач объем памяти потребляемый Apache HTTP Server постоянно колеблется, к примеру: несколько минут назад (после небольшого простоя бездействия ноутбука было 170Мб), сейчас (спустя минут 10) - 60 Мб. Собственно сама функция. Не могу понять в чем проблема и почему phpQuery::unloadDocuments(); как-то избирательно очищает документы
PHP:
скопировать код в буфер обмена
  1. function parcer($url){
  2. $ids=[];
  3. $indexIds=0;
  4. $content = get_content($url);
  5.  
  6. $doc = phpQuery::newDocument($content);
  7.  
  8. foreach ($doc->find('[id^=name_]:input') as $opt) { // получаем товары которые успели преобразоваться в input
  9.         $opt=pq($opt);
  10.         $numTov = preg_replace('~[^0-9]*~','',$opt->attr('id')); // получаем с ID номер товара
  11.         $ids[$indexIds][] = $numTov;
  12.         $ids[$indexIds][] = $opt->attr('value'); // получаем значение input
  13.         $ids[$indexIds][] = $opt->nextAll('input:first-of-type')->prev('a')->text(); //ищем последнюю ссылку каталога
  14.         $ids[$indexIds][] = $opt->nextAll('nobr')->children('[id^=manf]')->text(); //ищем поставщика
  15.         $indexIds++;
  16. }
  17.  
  18. foreach ($doc->find('td>[id^=name_]:not(:input)') as $opt) { // получаем товары в span, которые без родителя
  19.         $opt=pq($opt);
  20.         $numTov = preg_replace('~[^0-9]*~','',$opt->attr('id'));
  21.         $ids[$indexIds][] = $numTov;
  22.         $ids[$indexIds][]= $opt->text();
  23.         $ids[$indexIds][] = $opt->nextAll('[id^=cats_]:last')->text();
  24.         $ids[$indexIds][] = $opt->nextAll('nobr')->children('[id^=manf]')->text();
  25.         $indexIds++;
  26. }
  27.  
  28. foreach ($doc->find('div>[id^=name_]') as $opt) { // получаем товары в span, которые с родителем
  29.         $opt=pq($opt);
  30.         $numTov = preg_replace('~[^0-9]*~','',$opt->attr('id'));
  31.         $ids[$indexIds][] = $numTov;
  32.         $ids[$indexIds][]= $opt->text();
  33.         $ids[$indexIds][] = $opt->parent()->nextAll('[id^=cats_]:last')->text();
  34.         $ids[$indexIds][] = $opt->parent()->nextAll('nobr')->children('[id^=manf]')->text();
  35.         $indexIds++;
  36. }
  37.  
  38. phpQuery::unloadDocuments(); //очистка документа
  39. gc_collect_cycles(); // принудительный вызов встроенного сборщика мусора PHP
  40. return $ids;
  41. }
 
 Top
LIME
Отправлено: 27 Мая, 2019 - 17:56:34
Post Id


Активный участник


Покинул форум
Сообщений всего: 10732
Дата рег-ции: Нояб. 2010  


Помог: 322 раз(а)




а возможно и где-то еще течет вне это ф-ции
выводи в консоль отладочную инфу
https://www.php.net/manual/ru/fu...ry-get-usage.php
в начале ф-ции, вне ф-ции, перед и после unloadDocuments итд
может надебажишь что
(Добавление)
я бы конечно вовнутрь полез и посмотрел что он там кэширует и как
в newDocument и unloadDocuments если выяснишь что именно он течет
 
 Top
mikka
Отправлено: 27 Мая, 2019 - 19:46:33
Post Id


Новичок


Покинул форум
Сообщений всего: 12
Дата рег-ции: Окт. 2018  


Помог: 0 раз(а)




LIME пишет:
а возможно и где-то еще течет вне это ф-ции
выводи в консоль отладочную инфу
https://www.php.net/manual/ru/fu...ry-get-usage.php
в начале ф-ции, вне ф-ции, перед и после unloadDocuments итд
может надебажишь что
(Добавление)
я бы конечно вовнутрь полез и посмотрел что он там кэширует и как
в newDocument и unloadDocuments если выяснишь что именно он течет


В том что дело phpQuery используется только в этой функции и больше нигде.
Вот снова получил эту ошибку

PHP Fatal error: Allowed memory size of 1610612736 bytes exhausted (tried to allocate 1073741824 bytes) in C:\OSPanel\domains\home-page-parcer.ru\phpQuery.php on line 3494

Спасибо за совет с памятью. Буду пытаться отладить.

(Отредактировано автором: 27 Мая, 2019 - 20:06:27)

 
 Top
LIME
Отправлено: 27 Мая, 2019 - 20:34:07
Post Id


Активный участник


Покинул форум
Сообщений всего: 10732
Дата рег-ции: Нояб. 2010  


Помог: 322 раз(а)




В какой момент закончилась память само по себе еще ничего не значит
Если используется фреймворк запусти в прод режиме
Они много всего пишут в профилировщик
Только выводит память чтоб не ждать до утра))
(Добавление)
Если все-таки случится затык
Запускай внутри цикла дочерний процесс передавая урл как параметр
Заодно распарраллелишь))
 
 Top
mikka
Отправлено: 28 Мая, 2019 - 11:56:24
Post Id


Новичок


Покинул форум
Сообщений всего: 12
Дата рег-ции: Окт. 2018  


Помог: 0 раз(а)




Провел небольшие исследования расставив в различных частях скрипта memory_get_usage.
Потребляемая память увеличивается непосредственно после создания объекта phpQuery из переменной $content , при этом память не уменьшается после вызова phpQuery::unloadDocuments(). Также, память накапливается не после каждого создания объекта phpQuery, а как-то периодически (один раз в несколько итераций, закономерность увеличения не удалось установить). К примеру: было 2097152 после стало 4194304, спустя несколько итераций значение не изменялось, но после снова увеличилось и стало 6291456.
Также хотелось бы добавить, что в некоторых случаях, память увеличивается не после создания объекта phpQuery, а после одного из циклов foreach (1-го либо 2-го сверху)
 
 Top
Страниц (1): [1]
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Программирование на PHP »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB