Утечка памяти

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
shamyyl
Сообщения: 5
Зарегистрирован: 2015.01.14, 15:26

Утечка памяти

Сообщение shamyyl »

Имеем код

Код: Выделить всё

$beforeCreate = memory_get_usage();
        
//Создаем объект ActiveRecord
$mailer = Mailer::findOne(20);
        
//Удаляем объект из памяти
unset($mailer);
$afterDelete = memory_get_usage();
 
по идее объем используемой памяти до создания объекта и после его удаления должен совпадать: $beforeCreate = $afterDelete,
однако на деле получаем: $beforeCreate < $afterDelete.

Почему unset не освобождает память,выделенную под объект?
Как тогда освободить эту память?
kawabanga
Сообщения: 806
Зарегистрирован: 2013.10.12, 23:35
Откуда: Новосибирск

Re: Утечка памяти

Сообщение kawabanga »

Код: Выделить всё

// comment out the following two lines when deployed to production
//defined('YII_DEBUG') or define('YII_DEBUG', true);
//defined('YII_ENV') or define('YII_ENV', 'dev'); 
В index.php
shamyyl
Сообщения: 5
Зарегистрирован: 2015.01.14, 15:26

Re: Утечка памяти

Сообщение shamyyl »

Пробовал, утечка остается.
feldwebel
Сообщения: 15
Зарегистрирован: 2011.03.09, 11:49

Re: Утечка памяти

Сообщение feldwebel »

Попробуй после unset() вызывать gc_collect_cycles()
shamyyl
Сообщения: 5
Зарегистрирован: 2015.01.14, 15:26

Re: Утечка памяти

Сообщение shamyyl »

Ненамного уменьшает память, тем не менее разница остается большая.
yan
Сообщения: 942
Зарегистрирован: 2011.03.23, 09:28
Откуда: Уфа

Re: Утечка памяти

Сообщение yan »

и что так сильно много памяти расходуется? попробуйте несколько раз сделать тоже самое - подозреваю память расходуется только в первый раз
shamyyl
Сообщения: 5
Зарегистрирован: 2015.01.14, 15:26

Re: Утечка памяти

Сообщение shamyyl »

yan писал(а):и что так сильно много памяти расходуется? попробуйте несколько раз сделать тоже самое - подозреваю память расходуется только в первый раз
Нет, "утекающая" память накапливается после каждого обращения.
В итоге затрудняется работа с большими объемами данных.
vismut
Сообщения: 64
Зарегистрирован: 2014.10.01, 16:46

Re: Утечка памяти

Сообщение vismut »

Суть в том, что там нужно доставать Over 300 000 записей, естесвенно это все делается пачками, таким образом как-раз и планировалось избежать любых проблем с памятью.

Только беда в том, что когда в цикле достаем записи, они копятся в оперативной памяти.
unset переменных, в которые были получены данные ActiveRecord, не приводит ни к чему толковому.
Тоесть ссылка(переменная) удаляется, а сами данные остаются, и при этом копятся...
yan
Сообщения: 942
Зарегистрирован: 2011.03.23, 09:28
Откуда: Уфа

Re: Утечка памяти

Сообщение yan »

а нужны ли при таких объемах модели, может asArray использовать?
vismut
Сообщения: 64
Зарегистрирован: 2014.10.01, 16:46

Re: Утечка памяти

Сообщение vismut »

Да уж думали и так, и сяк.
Там нужен ActiveRecord именно)
Таковы данные задачи.

Нужно понять как чистить память от моделей...
Аватара пользователя
yiijeka
Сообщения: 3103
Зарегистрирован: 2012.01.28, 09:14
Откуда: Беларусь
Контактная информация:

Re: Утечка памяти

Сообщение yiijeka »

Самое лучше, что вы можете сделать это unset($mailer);

Этот вызов означает, что $mailer удалится, но память не высвободится. Всё потому, что mailer это по сути ссылка на контейнер в памяти. На этот контейнер ссылаются Mailer атрибуты.

Всё само очистится, только когда скрипт завершится - по другому в php "утекающую память" не высвободить.

Переход на array не решит проблему утечки памяти, просто меньше будет её использоваться. Но утечка имеет место быть, при unset и ничего с этим не поделать :) Если вы упёрлись в лимит, то нужно изменять логику отдельных участков приложения.
ShNURoK
Сообщения: 168
Зарегистрирован: 2012.04.12, 05:44
Контактная информация:

Re: Утечка памяти

Сообщение ShNURoK »

Как вариант завершать процесс и создавать заново с нужной итерации.
astronin
Сообщения: 606
Зарегистрирован: 2012.01.30, 17:46

Re: Утечка памяти

Сообщение astronin »

пробовали делать echo а затем flash() ?
yan
Сообщения: 942
Зарегистрирован: 2011.03.23, 09:28
Откуда: Уфа

Re: Утечка памяти

Сообщение yan »

Samdark хорошо описал проблему http://rmcreative.ru/blog/post/utechki-pamjati-v-php, комментарии тоже полезны.
yan
Сообщения: 942
Зарегистрирован: 2011.03.23, 09:28
Откуда: Уфа

Re: Утечка памяти

Сообщение yan »

yiijeka писал(а): Переход на array не решит проблему утечки памяти, просто меньше будет её использоваться. Но утечка имеет место быть, при unset и ничего с этим не поделать :)
с массивами все таки утечка намного меньше получается по опыту
Аватара пользователя
chungachguk
Сообщения: 435
Зарегистрирован: 2012.07.17, 11:52

Re: Утечка памяти

Сообщение chungachguk »

vismut писал(а):Суть в том, что там нужно доставать Over 300 000 записей, естесвенно это все делается пачками, таким образом как-раз и планировалось избежать любых проблем с памятью.

Только беда в том, что когда в цикле достаем записи, они копятся в оперативной памяти.
unset переменных, в которые были получены данные ActiveRecord, не приводит ни к чему толковому.
Тоесть ссылка(переменная) удаляется, а сами данные остаются, и при этом копятся...
Помнится в книге PHP5 Котерова, была такая рекомендация: чтобы удалить переменную, то нужно было сначала присвоить ей пустое значение, а потом вызывать unset.
shamyyl
Сообщения: 5
Зарегистрирован: 2015.01.14, 15:26

Re: Утечка памяти

Сообщение shamyyl »

yiijeka писал(а): Самое лучше, что вы можете сделать это unset($mailer);

Этот вызов означает, что $mailer удалится, но память не высвободится. Всё потому, что mailer это по сути ссылка на контейнер в памяти. На этот контейнер ссылаются Mailer атрибуты.
Если бы дело было только в атрибутах класса...

Имея простейший класс:

Код: Выделить всё

class SomeClass
{
    public function method()
    {
        return true;
    }
} 
и код:

Код: Выделить всё

$beforeCreate = memory_get_usage();
        
//Создаем объект 
$object = new SomeClass;
        
//Удаляем объект из памяти
unset($object );
$afterDelete = memory_get_usage();
все равно получаем утечку $beforeCreate < $afterDelete
Аватара пользователя
yiijeka
Сообщения: 3103
Зарегистрирован: 2012.01.28, 09:14
Откуда: Беларусь
Контактная информация:

Re: Утечка памяти

Сообщение yiijeka »

Потому что память расходовалась на внутренние механизмы new SomeClass;
По правильному нужно было

Код: Выделить всё

        
//Создаем объект 
$object = new SomeClass;
$beforeCreate = memory_get_usage();
//Удаляем объект из памяти
unset($object );
$afterDelete = memory_get_usage();
Но там все равно будет разница. От этого не уйти. Никто, кроме самого php, не сможет очистить память. PHP выполняет очистку памяти автоматически. Вы не сможете явно удалить из памяти что-то. Вы сможете только поставить в очередь на удаление - это и есть unset() в вашем случае.
astronin
Сообщения: 606
Зарегистрирован: 2012.01.30, 17:46

Re: Утечка памяти

Сообщение astronin »

в принципе unset очищает память практически полностью, оставляя какие-то крохи байт где-то на поддерживающие механизмы (проверил на 5.5)
запустил в цикле $object = new SomeClass(); unset($object); память вообще ни как не растет по ходу цикла
кстати, присвоение null вообще ни как не помогает, хотя в предыдущих версиях может и помогала...

наверное вам стоит проверить свое приложение, и большая утечка где-то еще
может быть даже фреймворк где-то сжирает, тут вам уже надо пошагово проверять увеличение помяти в кодах фреймворка...
vismut
Сообщения: 64
Зарегистрирован: 2014.10.01, 16:46

Re: Утечка памяти

Сообщение vismut »

astronin писал(а):в принципе unset очищает память практически полностью, оставляя какие-то крохи байт где-то на поддерживающие механизмы (проверил на 5.5)
запустил в цикле $object = new SomeClass(); unset($object); память вообще ни как не растет по ходу цикла
кстати, присвоение null вообще ни как не помогает, хотя в предыдущих версиях может и помогала...

наверное вам стоит проверить свое приложение, и большая утечка где-то еще
может быть даже фреймворк где-то сжирает, тут вам уже надо пошагово проверять увеличение помяти в кодах фреймворка...
Пример с простым объектом не актуален)
Лучше сделайте так и скажите что тоже не растет)

Код: Выделить всё

//Создаем объект ActiveRecord
$object = SomeModel::findOne(1);
        
//Удаляем объект из памяти
unset($object);
 
Если и так у вас не будет отжирать память, тогда действительно странно)
Ответить