|
|
|||||
Регистрация: Nov 2009
Адрес: СПб
Сообщений: 2,236
|
Цитата:
Наблюдаю резкое сокращение времени жизни бесхозных объектов по мере увеличения версии плеера. Если в 10-м плеере объект без ссылки на него мог жить довольно долго, то сейчас в 11.6 он у меня перестает функционировать моментально. |
|
|||||
Регистрация: May 2011
Адрес: 0,0,0 относительно меня
Сообщений: 123
|
Провел вчера отличный вечер с GarbageCollector'ом и сотнями различных тестов.
Цитата:
public class Main extends Sprite { private var t:Timer; public function Main():void { if (stage) init(); else addEventListener(Event.ADDED_TO_STAGE, init); } private function init(e:Event = null):void { removeEventListener(Event.ADDED_TO_STAGE, init); // entry point var s:Sprite = new Sprite(); s.addEventListener(Event.ENTER_FRAME, lstnr); t = new Timer(1, 0); t.addEventListener(TimerEvent.TIMER, crt); t.start(); } private function lstnr(e:Event):void { trace(this); } private function crt(e:TimerEvent):void { var tf:TextField = new TextField(); } } Действительно ли необходимо уничтожать слушатели для удаляемых объектов? Или это надо делать по каким-то другим причинам? |
|
|||||
Регистрация: Nov 2009
Адрес: СПб
Сообщений: 2,236
|
А что именно удивляет?
|
|
|||||
Регистрация: Nov 2011
Сообщений: 41
|
Наличие слушателей у класса и наличие слушателей у свойств этого класса не спасает класс от удаления сборщиком мусора (протестировано с принудительным вызовом gc). С чего вообще пошла молва о том, что слушатели надо удалять перед удалением объекта? Понятно, что при потере ссылки на объект, слушатели продолжают выполнять свою функцию до срабатывания gc, но еще раз, наличие слушателей не препятствует тому, чтобы gc и съел объект и остановил функцию слушателя.
|
|
|||||
Регистрация: Nov 2009
Адрес: СПб
Сообщений: 2,236
|
Не совсем так. Вот тут не пропадает, хоть таймер и локальный.
package { import flash.display.Sprite; import flash.events.*; import flash.utils.*; import flash.text.*; public class Main extends Sprite { public function Main():void { if (stage) init(); else addEventListener(Event.ADDED_TO_STAGE, init); } private function init(e:Event = null):void { removeEventListener(Event.ADDED_TO_STAGE, init); // entry point var t:Timer = new Timer(1, 0); t.addEventListener(TimerEvent.TIMER, crt); t.start(); } private function crt(e:TimerEvent):void { var tf:TextField = new TextField(); trace(this); } } } Цитата:
Просто у объектов разная природа и, например, таймеры GC не трогает. Не останавливает, не удаляет, в итоге объекты давно уже удалены со сцены, но продолжают функционировать и отбирать на себя ресурс ФП. Добавлено через 13 минут На самом деле, я лично пользуюсь тремя очень простыми правилами: 1. От листенеров на одноразовые события всегда отписываемся в обработчиках. 2. Листнеры на пользовательские события (напр., нажатие кнопок, маусовер и т.д.) или события контейнера, в том числе от детей, копошащихся в контейнере, ставим с useWeakReference=true и не паримся (на самих детей вообще стараемся листенеров не ставить). 3. Листенеры на таймерах учитываем крайне аккуратно, всегда перед удалением объектов останавливаем их таймеры и отписываемся от листенеров. Случаи листенеров, которые не подпадают под эти три вида, разбираем отдельно. Впрочем, не исключаю, что у кого-то будет другое мнение по поводу работы с листенерами. |
|
|||||
Регистрация: Nov 2011
Сообщений: 41
|
mikhailk, спасибо, я понял, что с таймером у gc особые отношения.
Я завёл массив объектов win, в каждом из которых 5000 textField, добавил слушатели на каждый textfield, а также добавил слушатель на каждый элемент массива объектов win. Потом просто удаляю методом splice элемент из массива объектов win, смотрю что показывает профайлер: профайлер показывает что память освободилась, несмотря на то что 5000+1 слушателей живы. |
|
|||||
Регистрация: Jan 2009
Сообщений: 1,651
|
Цитата:
__________________
мой пустой блог |
|
|||||
Цитата:
Я вложенные объекты зануляю только в случае слишком частого созадания/удаления. Скаежм так я знаю что удаления объекта держателя достаточно для удаления его локальных объектов не имеющих других ссылок, но нет уверенности в том, что зануление вложенных объектов не оптимизирует, ускоряет работу GC. ПОдозреваю что зануление вложенных объектов может не сколько ускорить работу GC сколько при следующем запросе FP на выделение памяти сделать этот запрос меньше, но не имею на этот счет никаких доказательств )
__________________
... Последний раз редактировалось Александр Мостовой; 23.03.2013 в 17:37. |
|
|||||
Регистрация: Jan 2009
Сообщений: 1,651
|
Принудительный вызов ГС есть только в дебаг-плеере. В релизе же он работает "как звезды лягут" в зависимости от версии плеера, свободной памяти и черти чего еще.
Главная проблема, то, что нигде нет собранных данных на эту тему. Особенно там, где хотелось бы эту инфу видеть - в манах. Окей. Локальная переменная функции освободится несмотря на слушатель ENTER_FRAME. Локальный таймер не освободится. Освободится ли локальная переменная-спрайт со слушателем ENTER_FRAME, если ее добавить на сцену? Мм, скорее всего нет. А если addChild'ить его в другой спрайт, который на сцене? А когда этот спрайт-родитель уберут со сцены, то осободится ли? Если у меня есть объект, у которого есть свойство-спрайт и этот спрайт подписан на ENTER_FRAME, освободится ли от него память, когда на объект не останется ссылок, а спрайт убран со сцены? Короче говоря, слишком много "если". Так много, что можно или потратить очень много времени на тесты, или просто занулять/отписывать все подрят на всякий случай.
__________________
мой пустой блог |
Часовой пояс GMT +4, время: 00:49. |
|
« Предыдущая тема | Следующая тема » |
|
|