PHP и память

Lewik

Новичок
Мне часто приходится писать долгоиграющие скрипты на symfony, работающие в фоне, коненчо же с бд, конечно же циклы по несколько тысяч итераций.

Если не предпринять мер, то скрипт может работать крайне неэффективно. Например: 40 минут и сожрать 700 метров. С мерами - 2 минуты и 45 метров.

90% результата дает отключение логирования доктрины, остальное это принудительное удаление объектов с циклическими ссылками и обычые unset. Но этих мер бывает недостаточно.

Вопросы: есть ли инструмент для получения размера занимаемой памяти переменной? Размер может быть относительный. Получается надо узнавать список глобальных переменных (или переменных, видимых в строке применения дампа) а так же свойств объектов и элементов массива. Мне кажется это должно быть некое расширение php, которое смотрит "память" php в нужный момент и дампит ее чтобы потом разобрать.
 

Lewik

Новичок
Я пробовал через xedebug. Я не нашел способа получить список переменных + свойста методов и элементы массивов. Получить список глобальных переменных - получилось.
Я тухлый скриптовик. Че за runtime? =) Мне было бы полезно получить вышеприведенный список в определенном месте кода. Вероятно это и имеется ввиду.
 

Lewik

Новичок
AnrDaemon, спасибо.
Redjik, помимо прочего хорошо бы и в рантайм.

Вообще, после того, как "закончилась" область видимости переменной или произошел unset - она должна удаляться. Исключение - на нее есть ссылки. Запуск gc_collect_cycles() должен удалить все кольцевые ссылки. Я надеюсь больше подвохов нет. Не по какой то причине память все равно растет. И я не могу найти на какие значения переменных сохраняются ссылки.
 

Redjik

Джедай-мастер
про инструменты, для исследования Runtime не знаю, думаю нет таких

http://stackoverflow.com/questions/849549/diagnosing-memory-leaks-allowed-memory-size-of-bytes-exhausted
http://peterwang.info/blog/2013/05/18/finding-memory-leaks-in-long-running-php-script/

пробуй - проблема стара как php

скрипты в PHP очень часто текут, особенно в ООП разрезе... никого это не напрягает ибо обычно время жизни скрипта очень малО

Могу предположить, что можно вызывать долгоиграющие скрипты через форки (сам не проверял и не ковырял реализацию форков в php)

Предположим, что пишем демона на php.
Моя теория:
1) Создаем мастер процесс - буквально из 4х строчек.
2) Форкаем
3) В ребенке подключаем ООП фарш
4) Отслеживаем время жизни
5) Ребенок самоубивается - возвращает родителю необходимую информацию
6) Адресное пространство форка очищается, память освобождается
7) Родителем создаем новый форк.

Повторяю - это только теория ибо не хватает знаний по реализации, надо исследовать. Ну или тупо оттестировать.

ЗЫ. вот подобные соображения нагуглилилсь
https://www.adayinthelifeof.nl/2013/07/10/phps-resources-and-garbage-collection/
 

Lewik

Новичок
не - оно для другого
Я наверно опять криво выразился. Я имел ввиду, что он удаляет удаленные переменные, которые имели циклические ссылки друг на друга. Когда их удаляли - refcount был больше 0 и они как таковые не удалились.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
таких инструментов нет.
доктрина известна тем, что не предназначена для фоновых долгоживущих процессов, лучше напиши все руками - быстрее выйдет
 

Redjik

Джедай-мастер
grigori, а по поводу моей теории - пробовал такое?
мастер процесс создает дочек, которые дергают доктрину.
такое будет течь?

ЗЫ. пошел тестить =)))
 

Breeze

goshogun
Команда форума
Партнер клуба
grigori, а по поводу моей теории - пробовал такое?
мастер процесс создает дочек, которые дергают доктрину.
такое будет течь?

ЗЫ. пошел тестить =)))
тут от конкретной задачи шагать можно.
например, был робот-проверяльщик сайтов на HTTP 200 в контороском каталоге, старый, лет 12 ему, кто писал хз.
стал работать в итоге суток по 5 и падать из-за нехватки памяти(4гб)

вот его переписал на форк с разделением общей массы ссылок между чайлдами +сделал деструктор с циклическим unset по свойствам объекта.
в итоге за 3 часа обходит всех и в пике жрет 350Мб.

ЗЫ: ну и была еще бага одна, тоже хорошо ела память из-за неправильной обработки 301 редиректа.

т.е. надо сначала найти кто ест, а потом уже думать как обойти.
синтетика не поможет
 

Redjik

Джедай-мастер
угу, у себя проверил, тоже показало, что форки решают проблему с утечками
понятно теперь, почему phpUnit можно настраивать на тестирование в отдельном процессе
 

Redjik

Джедай-мастер
simple_html_dom например течет стабильно как его ни unset()... ковырять его лень
 

Lewik

Новичок
То, что форки не будут течь - очевидно.
Манагер, который управляет форками тоже должен писать в базу.
Но мне кажется, это костыль.

Мне кажется это не доктрина течет.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
я писал скрипты, которые форкались, жили долго и счастливо, и умирали в один день через пару недель - зависал мастер. просто зависал через длительное время, руками рестартовался по kill -9
но это было давно, до 5.3 и gc, ситуация должна была улучшиться
 

fixxxer

К.О.
Партнер клуба
Аккуратно написанный мастер будет работать годами. Пара моментов:
1) если могут быть кольцевые ссылки - не забывать gc_collect_cycles, но мастер вполне можно написать так, чтобы их и не было - все ООПэ в детки
2) не надо самому писать демонизацию, обработку pid и все такое, не 2000й год. Пишется обычный cli, запускать upstart-ом или systemd с respawn
3) в верхнем обработчике исключений вести подсчет, сколько их навалило за последние N секунд, и при превышении лимита аккуратно падать - upstart/systemd перезапустит
 

Redjik

Джедай-мастер
fixxxer, не понял, если через systemd запускать скрипт, зачем чисто при исключениях падать? нам же нужно падать при критичном значении памяти + ошибки

ЗЫ. я так понял под пунктом 1 у тебя вариант для 2000го года при обработке pid в мастер процессе =), 2 и 3 уже про systemd и единственный мастер процесс, без деток
 

Redjik

Джедай-мастер
прикольно тема повернулась - может в теорию надо?
 
Сверху