Форум программистов, компьютерный форум, киберфорум
PHP: ООП
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.83/35: Рейтинг темы: голосов - 35, средняя оценка - 4.83
0 / 0 / 0
Регистрация: 27.08.2013
Сообщений: 8
1

Выявить утечку памяти

23.08.2014, 21:44. Показов 6668. Ответов 19
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте. Написал парсер с библиотекой для парсинга simple_html_dom. После длительного парсинга видно, что память переполняется. Можно ли как то узнать, в каком месте идет переполнение памяти ? Профайлер может
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
23.08.2014, 21:44
Ответы с готовыми решениями:

Выделение памяти, проверка на утечку памяти
Интересуют два вопроса: 1. Правильно ли устроен алгоритм выделения, удаление и запись ячейки...

Найти утечку памяти
Помогите найти утечку памяти #include <stdio.h> #include <stdlib.h> struct Rebro { int val;...

Проверка на утечку памяти
Всем доброго времени суток. Сразу оговорюсь, я не профессионал, программирование - моё хобби,...

Проверка на утечку памяти
Есть оконное приложение где куча контейнеров и т.д. Как можно проверить, есть ли утечки памяти?...

19
F́́́́́́́ŕ́́́́́́́é́́́ ́ak
259 / 223 / 109
Регистрация: 07.07.2014
Сообщений: 965
24.08.2014, 17:57 2
Пробовал ловить утечки памяти в большом проекте - дело совершенно неблагодарное.

Первое что я сделал - попробовал повтыкать везде memory_get_usage, - ничего толком не получилось.

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

Потом пробовал различные профайлеры - они в принципе ничего не дали, кроме красивой картинки..

Еще помню пробовал играться с версией PHP, накатывать различные патчи.. ничего особо не помогло.. =)

Затем я вернулся к первому способу и таки нашел утечку памяти.. в PECL'овом расширении amqp для PHP..

Соответственно не могу ничего конкретного посоветовать, - утечки памяти ловить сложнее других ошибок и конкретного рецепта как с ними бороться - не существует.
0
168 / 0 / 1
Регистрация: 25.08.2014
Сообщений: 6
25.08.2014, 13:27 3
simple_html_dom - это PHP библиотека, поэтому говорить об "утечке" памяти тут не приходится. PHP устроен так, что для каждой сессии(клиентского запроса от веб-сервера или другого SAPI) образует отдельный блок памяти(ограниченный сверху настройками), который привязан к этой сессии. Превышение лимита дает всем знакомое сообщение, в котором как раз и указано - где именно осуществляют попытку выделить очередной кусок из блока, который становится фатальным. Важно понимать, что не только PHP код может вызвать превышение лимита - каждый include`нутый файл представляет собой байт-код(+к использованной памяти), служебные структуры, описывающие контекст этого байт-кода(+к использованной памяти) и много чего еще(даже отложенное создание классов на деле реализовано как дублирование записи в соответствующей hash-таблице).

По-сему:
1. unset переменных, которые далее по коду не нужны
2. повышение лимита в настройках
0
249 / 249 / 98
Регистрация: 26.07.2010
Сообщений: 1,685
25.08.2014, 14:46 4
по-моему сам simple_html_dom довольно кривоватый, пользовался им, возникали такие же проблемы при больших объемах, поэтому если не слишком сложный парсинг, лучше использовать регулярки, также посоветовал бы вам обратить внимание на PHPQuery
0
F́́́́́́́ŕ́́́́́́́é́́́ ́ak
259 / 223 / 109
Регистрация: 07.07.2014
Сообщений: 965
25.08.2014, 16:43 5
asmprog, речь очевидно идет о CLI-демоне, ваше сообщение немного о другом.

Цитата Сообщение от asmprog Посмотреть сообщение
simple_html_dom - это PHP библиотека, поэтому говорить об "утечке" памяти тут не приходится
Глупости, утчеки памяти могут быть где угодно. Как я уже писал выше - лично находил утечку в пхп'шной либе.

Цитата Сообщение от asmprog Посмотреть сообщение
1. unset переменных, которые далее по коду не нужны
Глупость, unset - пережиток PHP4, в подавляющем большинстве случаев он не нужен - gc сейчас и сам отлично удаляет ненужные переменные.

Цитата Сообщение от asmprog Посмотреть сообщение
2. повышение лимита в настройках
Чем это поможет? - Ну сдохнет парсер не через 2 часа, а через 4, через день?

Цитата Сообщение от V@D!k Посмотреть сообщение
по-моему сам simple_html_dom довольно кривоватый
И это никак не мешает найти строчку вызов которой приводит к утечке памяти, а потом написать баг-репорт разработчикам, если это их косяк =) Хотя маловероятно, что косяк там, т.к.:
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
$string = <<<XML
<?xml version='1.0'?> 
<document>
 <title>Forty What?</title>
 <from>Joe</from>
 <to>Jane</to>
 <body>
  I know that's the answer -- but what's the question?
 </body>
</document>
XML;
 
for($i = 0; $i < 10; $i ++){
        $xml = simplexml_load_string($string);
        print memory_get_usage() . PHP_EOL;
}
Судя по этому - с либой все нормально, возможно проблема есть на специфических XML'ках. Попробовать скормить в этот скрипт те xml'ки которые вызывают проблему - посмотреть.
0
249 / 249 / 98
Регистрация: 26.07.2010
Сообщений: 1,685
25.08.2014, 17:39 6
увидел интересную ссылку, почитайте, может быть вам поможет
p.s. самое главное в конце
0
168 / 0 / 1
Регистрация: 25.08.2014
Сообщений: 6
25.08.2014, 17:50 7
Цитата Сообщение от Tatikoma Посмотреть сообщение
asmprog, речь очевидно идет о CLI-демоне, ваше сообщение немного о другом.
CLI-демон(Command Line Interface?) =) Глупости вашей нет предела? =) Или может быть все таки CGI(FastCGI)-демон? Да будет Вам известно, что все что "компилирует" PHP код называется SAPI и поддерживает общий интерфейс, в рамках которого требуется вызывать функции движка PHP php_request_startup/php_request_shutdown для обозначения "границ" запроса клиента перед непосредственной компиляцией PHP кода.

Цитата Сообщение от Tatikoma Посмотреть сообщение
Глупости, утчеки памяти могут быть где угодно. Как я уже писал выше - лично находил утечку в пхп'шной либе.
В PHP extension утечка быть может, а "где угодно" нет!

Цитата Сообщение от Tatikoma Посмотреть сообщение
Глупость, unset - пережиток PHP4, в подавляющем большинстве случаев он не нужен - gc сейчас и сам отлично удаляет ненужные переменные.
unset вызывает деструктор(dtor) переменной, т.е. разрушается экземпляр класса, массив(и все что в массиве), память выделенная под строку освобождается. А gc вызывает цикл сборки мусора как раз при завершении сессии.

Цитата Сообщение от Tatikoma Посмотреть сообщение
Чем это поможет? - Ну сдохнет парсер не через 2 часа, а через 4, через день?
Возможно, человеку банально не хватает памяти конкретный файл или порцию данных обработать.

P.S. не советую Вам, Tatikoma, пороть хрень с умным видом(не в лучшем свете себя выставляете), а уж тем более спорить со мной о внутренностях интерпретатора(движка Zend в частности), поскольку я уже года 3 копаюсь в исходниках, а вот Вы в элементарных вещах умудрились запутаться.
0
F́́́́́́́ŕ́́́́́́́é́́́ ́ak
259 / 223 / 109
Регистрация: 07.07.2014
Сообщений: 965
25.08.2014, 21:54 8
asmprog, вы зря употребляете слово "компиляция" к PHP-коду, т.к. ни трансляция в байт-код, не исполнение байт-кода компиляцией по-факту не является.

Цитата Сообщение от asmprog Посмотреть сообщение
В PHP extension утечка быть может, а "где угодно" нет!
Под "где угодно" подразумеваются лишь места, где она может быть. Например в ядре ОС =)

Цитата Сообщение от asmprog Посмотреть сообщение
unset вызывает деструктор(dtor) переменной, т.е. разрушается экземпляр класса, массив(и все что в массиве), память выделенная под строку освобождается. А gc вызывает цикл сборки мусора как раз при завершении сессии.
PHP
1
2
3
4
function test(){
    $x = 'abc';
}
test();
Т.е. место под переменную $x - останется занятым? - Не-не-не, неиспользуемые переменные PHP сам удаляет без подсказок.

Цитата Сообщение от asmprog Посмотреть сообщение
Возможно, человеку банально не хватает памяти конкретный файл или порцию данных обработать.
Перечитайте первый пост. Человеку возможно памяти и не хватает, а компьютеру более чем достаточно - жалоба на то, что после нескольких итераций цикла объем используемой памяти неумолимо растет, хотя предполагается что после каждой итерации данные куда-то сохраняются (куда-то т.е. скриптом, например в файл) и память очищается.

Цитата Сообщение от asmprog Посмотреть сообщение
P.S. не советую Вам, Tatikoma, пороть хрень с умным видом(не в лучшем свете себя выставляете), а уж тем более спорить со мной о внутренностях интерпретатора(движка Zend в частности), поскольку я уже года 3 копаюсь в исходниках, а вот Вы в элементарных вещах умудрились запутаться.
Переходите на PHP5, там более интересные исходники, чем в вашей версии =)

PS: Даже не нашелся что ответить на ваш выпад в послесловии. Предлагаю воздержаться от перехода на личности и сохранить нетралитет дискуссии, т.к. сливание обсуждения в холивар - плохая привычка.
0
168 / 0 / 1
Регистрация: 25.08.2014
Сообщений: 6
26.08.2014, 18:37 9
Цитата Сообщение от Tatikoma Посмотреть сообщение
asmprog, вы зря употребляете слово "компиляция" к PHP-коду, т.к. ни трансляция в байт-код, не исполнение байт-кода компиляцией по-факту не является.


Цитата Сообщение от Tatikoma Посмотреть сообщение
Перечитайте первый пост. Человеку возможно памяти и не хватает, а компьютеру более чем достаточно - жалоба на то, что после нескольких итераций цикла объем используемой памяти неумолимо растет, хотя предполагается что после каждой итерации данные куда-то сохраняются (куда-то т.е. скриптом, например в файл) и память очищается.

Перечитал, вот полная цитата(Вы в отдельном мире живете, где "длительный парсинг" равнозначен "нескольким итерациям цикла"?):

Здравствуйте. Написал парсер с библиотекой для парсинга simple_html_dom. После длительного парсинга видно, что память переполняется. Можно ли как то узнать, в каком месте идет переполнение памяти ? Профайлер может
Цитата Сообщение от Tatikoma Посмотреть сообщение
Т.е. место под переменную $x - останется занятым? - Не-не-не, неиспользуемые переменные PHP сам удаляет без подсказок.
Для начала нужно понять что происходит.

PHP
1
2
3
4
function test(){
    $x = 'abc';
}
test();
Упрощенно:
1. Движок Zend регистрирует ф-цию test, разбирает ее на байт-код И ДОБАВЛЯЕТ В КОНЦЕ ОПКОД ZEND_RETURN
2. Переводит в байт-код вызов ф-ции test
3. Добавляет в конце безымянной ф-ции(точки входа) опкод ZEND_RETURN
4. Затирает опкод ZEND_DECLARE_FUNCTION опкодом ZEND_NOP(второй проход)

При вызове test, когда курсор виртуальной машины дойдет до опкода ZEND_RETURN в конце обработчика опкода(можно посмотреть в файле Zend\zend_vm_def.h) происходит передача управления хелперу

C
1
2
3
4
5
6
ZEND_VM_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY)
{ 
...
    FREE_OP1_IF_VAR();
    ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
}
В самом начале которого:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
{
...
    if (!EG(active_symbol_table)) {
        zval ***cv = EX(CVs);
        zval ***end = cv + EX(op_array)->last_var;
        while (cv != end) {
            if (*cv) {
                zval_ptr_dtor(*cv);
            }
            cv++;
        }
    }
}
вызывается деструктор всех ИНИЦИАЛИЗИРОВАННЫХ переменных.

zval_ptr_dtor при этом является макросом, указывающим на функцию
C
1
ZEND_API void _zval_ptr_dtor(zval **zval_ptr ZEND_FILE_LINE_DC)
внутри которой(ЕСЛИ счетчик ссылок на переменную будет == 0) вызывается(после уничтожения содержимого переменной - такая уж судьба, что переменная и содержимое не всегда хранятся вместе)
C
1
efree_rel(zv);
efree_rel в свою очередь ведет к
C
1
ZEND_API void _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
, которая и "освобождает" переменную
C
1
_zend_mm_free_int(AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
А что будет если посмотреть код _zend_mm_free_int(Zend\zend_alloc.c)? Правильно, никакого освобождения памяти не происходит. Сначала берут блок, в котором хранится переменная. Помечают как освобожденный. Если след. блок свободен склеивают. Если предыдущий тоже свободен, склеивают предыдущий с текущим блоком. Уменьшают размер кучи текущей сессии. Но память системе не возвращается, чтобы всегда можно было выделить новый блок из свободных нужного размера.

-----------------------------------------------
---------------------НО-----------------------

Все это происходит КОГДА осуществляется выход из ф-ции. А вот то, о чем я говорил:
Цитата Сообщение от asmprog Посмотреть сообщение
1. unset переменных, которые далее по коду не нужны
Цитата Сообщение от Tatikoma Посмотреть сообщение
Переходите на PHP5, там более интересные исходники, чем в вашей версии =)
Весь C код, который я привел взят из исходников 5.3.8. Если этот пассаж выполнен в контексте
Цитата Сообщение от asmprog Посмотреть сообщение
поскольку я уже года 3 копаюсь в исходниках
, то выводы довольно сомнительные, поскольку PHP 5(из вики)
Пятая версия PHP была выпущена разработчиками 13 июля 2004 года.
Заключение: "утечек" памяти в PHP коде нет и быть не может. Могут существовать ошибки в коде движка Zend, интерпретатора, SAPI или расширения. Если хотите разобраться в менеджере памяти, Zend\zend_alloc.c в помощь.
0
F́́́́́́́ŕ́́́́́́́é́́́ ́ak
259 / 223 / 109
Регистрация: 07.07.2014
Сообщений: 965
27.08.2014, 11:10 10
Цитата Сообщение от asmprog Посмотреть сообщение
"утечек" памяти в PHP коде нет и быть не может.
Исключительно если использовать термин утечки памяти как низкоуровневое понятие.

Случайно забытый элемент массива - чем не утечка памяти?
0
168 / 0 / 1
Регистрация: 25.08.2014
Сообщений: 6
27.08.2014, 11:39 11
Цитата Сообщение от Tatikoma Посмотреть сообщение
Случайно забытый элемент массива - чем не утечка памяти?
А я смотрю, Вы неугомоннный, так ведь? Сначала у Вас CLI может быть демоном. Потом сами для себя пост ТС переврали, в чем и меня пытались "убедить". Теперь "утечка памяти" у Вас носит не тот смысл, которым данный термин все НОРМАЛЬНЫЕ программисты наделяют. Что такое? Увидели новорега(меня) на форуме и ринулись ему свой авторитет доказывать? Да только новорег не такой простой оказался? Вот и приходится в спешном порядке цепляться к слову "компиляция" и утечкой памяти называть то, что ей не является, только бы сохранить "хорошую мину при плохой игре"?
0
ads
27.08.2014, 12:21
  #12

Не по теме:

Цитата Сообщение от asmprog Посмотреть сообщение
гупости вашей нет предела
Цитата Сообщение от asmprog Посмотреть сообщение
пороть хрень с умным видом
Цитата Сообщение от asmprog Посмотреть сообщение
поскольку я уже года 3 копаюсь
Цитата Сообщение от asmprog Посмотреть сообщение
Увидели новорега(меня) на форуме и ринулись ему свой авторитет доказывать
черт, авторитет! "я", "меня"... похоже слово авторитет вас волнует больше чем кого-то еще на этом форуме.

0
Почетный модератор
Эксперт HTML/CSSЭксперт PHP
16844 / 6723 / 880
Регистрация: 12.06.2012
Сообщений: 19,967
27.08.2014, 13:59 13
Мда.. Веселое обсуждение, нечего сказать. Столько слов об утечке памяти.. И что-то никто не предложил, к примеру, парсить xml по частям. Непонятно, чем тут поможет то, что будешь знать место "утечки"

Не по теме:

Цитата Сообщение от asmprog Посмотреть сообщение
поскольку я уже года 3 копаюсь в исходниках
Нафига..?

0
249 / 249 / 98
Регистрация: 26.07.2010
Сообщений: 1,685
27.08.2014, 14:04 14
я ошибаюсь, или человек парсит контент с другого сайта а не с xml?
0
Почетный модератор
Эксперт HTML/CSSЭксперт PHP
16844 / 6723 / 880
Регистрация: 12.06.2012
Сообщений: 19,967
27.08.2014, 14:06 15
html, xml, какая разница.. А вот то, что с другого сайта - необязательно. Но если дело в этом, то, скорее всего, стоит сначала перекинуть контент к себе и парсить локально
0
249 / 249 / 98
Регистрация: 26.07.2010
Сообщений: 1,685
27.08.2014, 14:11 16
наверное вы правы, но мы не узнаем истины, пока создатель темы не скажет, что он парсит
0
Игорь[Igor]
27.08.2014, 14:30
  #17

Не по теме:

Цитата Сообщение от KOPOJI Посмотреть сообщение
Нафига..?
Утечку ищет

0
KOPOJI
27.08.2014, 14:31
  #18

Не по теме:

Игорь[Igor], :D

0
Tatikoma
27.08.2014, 18:10
  #19

Не по теме:

Цитата Сообщение от KOPOJI Посмотреть сообщение
Непонятно, чем тут поможет то, что будешь знать место "утечки"
Исправишь ошибку и утечка пропадет, очевидно же. Или же будешь использовать workaround, если устранить утечку затруднительно, как ты и предлагаешь.

Цитата Сообщение от asmprog Посмотреть сообщение
А я смотрю, Вы неугомоннный, так ведь? Сначала у Вас CLI может быть демоном. Потом сами для себя пост ТС переврали, в чем и меня пытались "убедить". Теперь "утечка памяти" у Вас носит не тот смысл, которым данный термин все НОРМАЛЬНЫЕ программисты наделяют. Что такое? Увидели новорега(меня) на форуме и ринулись ему свой авторитет доказывать? Да только новорег не такой простой оказался? Вот и приходится в спешном порядке цепляться к слову "компиляция" и утечкой памяти называть то, что ей не является, только бы сохранить "хорошую мину при плохой игре"?
Что вам от меня нужно? - Возьмите мой кошелек, только не насилуйте мозг..

0
KOPOJI
27.08.2014, 19:31     Выявить утечку памяти
  #20

Не по теме:

Цитата Сообщение от Tatikoma Посмотреть сообщение
Исправишь ошибку и утечка пропадет
ой, да какая там утечка. Там, скорее всего, идет обычное переполнение из-за больших аппетитов пыха. Надо было бы - уже давно переписали бы на Си и все.

0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
27.08.2014, 19:31

Изолировать утечку памяти
Есть давний проект. В нем есть утечка памяти. Разобраться с самой утечкой - долго, там, судя по...

Найти утечку памяти
Приветствую всех! Много раз слышал, что с помощью CodeGuard можно проверить есть ли в приложении...

Определить утечку памяти
Помогите найти утечку памяти. Вот код: #include &lt;stdio.h&gt; #include &lt;stdlib.h&gt; int max(int...

Как устранить утечку памяти?
Во время работы этого кода происходит утечка памяти: &lt;html&gt; &lt;head&gt; &lt;link rel=&quot;stylesheet&quot;...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru