Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Правильное удаление объекта (http://www.flasher.ru/forum/showthread.php?t=196061)

mikhailk 22.03.2013 22:48

Цитата:

В обычном режиме gb вызывается при нехватке паямти
Подозреваю, что не совсем так.
Наблюдаю резкое сокращение времени жизни бесхозных объектов по мере увеличения версии плеера.
Если в 10-м плеере объект без ссылки на него мог жить довольно долго, то сейчас в 11.6 он у меня перестает функционировать моментально.

zxcv 23.03.2013 14:53

Провел вчера отличный вечер с GarbageCollector'ом и сотнями различных тестов.

Цитата:

Сообщение от caseyryan (Сообщение 1125784)
Нет, не достаточно. Слушатель добавленный к объекту - имеет такую же ссылку на объект, как и переменная экземпляра (reference variable). Ее нужно тоже занулять.

Код AS3:

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();
                }
        }

Объясните мне теперь, пожалуйста, с***ли трэйс пропадает?
Действительно ли необходимо уничтожать слушатели для удаляемых объектов? Или это надо делать по каким-то другим причинам?

mikhailk 23.03.2013 16:07

А что именно удивляет?

samana 23.03.2013 16:19

Цитата:

Сообщение от zxcv (Сообщение 1126447)
Объясните мне теперь, пожалуйста, с***ли трэйс пропадает?

Значит локальные переменные не спасёт даже подписка на события.

Black Soviet 23.03.2013 16:30

Наличие слушателей у класса и наличие слушателей у свойств этого класса не спасает класс от удаления сборщиком мусора (протестировано с принудительным вызовом gc). С чего вообще пошла молва о том, что слушатели надо удалять перед удалением объекта? Понятно, что при потере ссылки на объект, слушатели продолжают выполнять свою функцию до срабатывания gc, но еще раз, наличие слушателей не препятствует тому, чтобы gc и съел объект и остановил функцию слушателя.

mikhailk 23.03.2013 16:31

Не совсем так. Вот тут не пропадает, хоть таймер и локальный.

Код AS3:

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);
                }
        }
 
}

Добавлено через 3 минуты
Цитата:

С чего вообще пошла молва о том, что слушатели надо удалять перед удалением объекта? Понятно, что при потере ссылки на объект, слушатели продолжают выполнять свою функцию до срабатывания gc, но еще раз, наличие слушателей не препятствует тому, чтобы gc и съел объект и остановил функцию слушателя.
Это очень опасное заблуждение.
Просто у объектов разная природа и, например, таймеры GC не трогает. Не останавливает, не удаляет, в итоге объекты давно уже удалены со сцены, но продолжают функционировать и отбирать на себя ресурс ФП.

Добавлено через 13 минут
На самом деле, я лично пользуюсь тремя очень простыми правилами:

1. От листенеров на одноразовые события всегда отписываемся в обработчиках.
2. Листнеры на пользовательские события (напр., нажатие кнопок, маусовер и т.д.) или события контейнера, в том числе от детей, копошащихся в контейнере, ставим с useWeakReference=true и не паримся (на самих детей вообще стараемся листенеров не ставить).
3. Листенеры на таймерах учитываем крайне аккуратно, всегда перед удалением объектов останавливаем их таймеры и отписываемся от листенеров.

Случаи листенеров, которые не подпадают под эти три вида, разбираем отдельно.

Впрочем, не исключаю, что у кого-то будет другое мнение по поводу работы с листенерами.

Black Soviet 23.03.2013 16:46

mikhailk, спасибо, я понял, что с таймером у gc особые отношения.

Я завёл массив объектов win, в каждом из которых 5000 textField, добавил слушатели на каждый textfield, а также добавил слушатель на каждый элемент массива объектов win.

Потом просто удаляю методом splice элемент из массива объектов win, смотрю что показывает профайлер: профайлер показывает что память освободилась, несмотря на то что 5000+1 слушателей живы.

iflamberg 23.03.2013 17:09

Цитата:

Наличие слушателей у класса и наличие слушателей у свойств этого класса не спасает класс от удаления сборщиком мусора (протестировано с принудительным вызовом gc). С чего вообще пошла молва о том, что слушатели надо удалять перед удалением объекта? Понятно, что при потере ссылки на объект, слушатели продолжают выполнять свою функцию до срабатывания gc, но еще раз, наличие слушателей не препятствует тому, чтобы gc и съел объект и остановил функцию слушателя.
Да кто-ж знает, съест или не съест. Вот я делал 4 года назад тесты аналогичные посту №12 и, клянусь, трейсы не пропадали, хоть ты тресни. Вот и приходится все занулять, все отписывать, чисто на всякий случай. Дурдом и фикция, чесслово. Зачем мне автоматический gc, если все равно приходится ручками все отписывать? Чем это отличается от cpp? Тем что я занулили все, а оно дейсвительно сотрется только когда gc соизволит? Лучше бы нормальный деструктор предусмотрели.

Александр Мостовой 23.03.2013 17:20

Цитата:

Вот я делал 4 года назад тесты аналогичные посту №12 и, клянусь, трейсы не пропадали,
Они пропадал, просто для проверки работы GC нужно было вызвать перегрузку памяти :) Но согласен, что с GC все сложно :)
Я вложенные объекты зануляю только в случае слишком частого созадания/удаления.

Скаежм так я знаю что удаления объекта держателя достаточно для удаления его локальных объектов не имеющих других ссылок, но нет уверенности в том, что зануление вложенных объектов не оптимизирует, ускоряет работу GC. ПОдозреваю что зануление вложенных объектов может не сколько ускорить работу GC сколько при следующем запросе FP на выделение памяти сделать этот запрос меньше, но не имею на этот счет никаких доказательств :))

iflamberg 23.03.2013 17:37

Принудительный вызов ГС есть только в дебаг-плеере. В релизе же он работает "как звезды лягут" в зависимости от версии плеера, свободной памяти и черти чего еще.
Главная проблема, то, что нигде нет собранных данных на эту тему. Особенно там, где хотелось бы эту инфу видеть - в манах.
Окей. Локальная переменная функции освободится несмотря на слушатель ENTER_FRAME. Локальный таймер не освободится. Освободится ли локальная переменная-спрайт со слушателем ENTER_FRAME, если ее добавить на сцену? Мм, скорее всего нет. А если addChild'ить его в другой спрайт, который на сцене? А когда этот спрайт-родитель уберут со сцены, то осободится ли? Если у меня есть объект, у которого есть свойство-спрайт и этот спрайт подписан на ENTER_FRAME, освободится ли от него память, когда на объект не останется ссылок, а спрайт убран со сцены?
Короче говоря, слишком много "если". Так много, что можно или потратить очень много времени на тесты, или просто занулять/отписывать все подрят на всякий случай.


Часовой пояс GMT +4, время: 14:15.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.