Просмотр полной версии : Количество ссылок на объект
Скажите, возможно ли во флеше получить число объектов, ссылайщихся на данный? Или может хотя бы есть эвент, возникающий при удалении объекта либо ссылки на него?
Psycho Tiger
22.08.2010, 21:29
Нет, невозможно.
Эвент есть. У него есть имя, которое нельзя произносить, но оное не важно: при удалении последней ссылки на объект нельзя поймать событие о том, что все ссылки были удаленны. Потому что событие тоже ловится через ссылку.
У сишников сборщика мусора нет - они выкручиваются с помощью прокси - счетчика сылок, чтобы знать когда уничтожать объект,
впринципе тоже можно сделать и для флеша, но нативно это сделать не удастся
В каждом элементе, использующем объект нужно будет ослеживать момент, когда он более не используется и говорить об этом счетчику ссылок.
Psycho Tiger
22.08.2010, 23:39
expl, забавно =)
Однако я придерживаюсь мнения что автору это нафиг ненужно. Либо цель образовательная, либо он что-то делает неправильно.
expl, забавно =)
Однако я придерживаюсь мнения что автору это нафиг ненужно. Либо цель образовательная, либо он что-то делает неправильно.
неправильно как раз доверять корявому сборщику мусора, который работает только когда память окончательно заканчивается
неправильно как раз доверять корявому сборщику мусора, который работает только когда память окончательно заканчивается
Чего это он корявый? По вашему он должен чистить память когда её полным полно?)
Количество ссылок на объект можно увидеть в profiler'e FlashBuilder.
А ещё есть CASA lib (http://casalib.org/blog/casa-lib-as3-release-1.3.0/), в ней почти все основные классы обладают методом destroy, который типо удаляет все ссылки на объект... но вобщем это в идеале, мне в свое время не помогло, в итоге написал свой destroy для плодящихся объектов, чего и вам советую.
Psycho Tiger
23.08.2010, 10:58
неправильно как раз доверять корявому сборщику мусора, который работает только когда память окончательно заканчивается
Ха-ха, ну хорошо)
Как Вы почистите память без GC?)
Чего это он корявый? По вашему он должен чистить память когда её полным полно?)
кроме флеша у пользователя запущены и другие приложения, которым тоже нужна память. И ему будет не очень приятно, если все это начнет тормозить
в итоге написал свой destroy для плодящихся объектов, чего и вам советую.
можно поподробнее?
можно поподробнее?
Ну э, метод в котором объект отписывается от слушателей, останавливает таймеры, удаляет внутренние объекты, обнуляет ссылки и тд и тп. За вас это делать никто не будет, так что придется об этом позаботится.
Robotex вы можете только подготовить объект к удалению из памяти, но не удалить
В CASALib, как я понял, по destroy() удаляются все ссылки на объект только в тех объектах, которые сами имплементят интерфейс IDestroyable. Т.е. если пользоваться только CasaSprite, CasaMovieClip, CasaLoader, Interval, DestroyableEventDispatcher и иже с ними, то все будет волшебно!
Zebestov
24.08.2010, 13:54
А не проще провоцировать GC, вместо всего этого огорода? Вот например у silin-а есть http://silin.su/#AS3/utils/gc
А не проще провоцировать GC, вместо всего этого огорода? Вот например у silin-а есть http://silin.su/#AS3/utils/gc
Какой смысл его провоцировать, если результата не будет?
Zebestov
24.08.2010, 14:04
Да... тему увели в сторону и я забыл о корнях проблемы =)
А можно подробней описать ситуацию, при которой на один объект есть неконтролируемое количество ссылок?
Количество ссылок всегда контролируемое. Мы же создаем их сами. И обнулять должны тоже сами. Единственное исключение, насколько я знаю - Dictionary, GC на ссылки в Dictionary не обращает внимания.
Zebestov
24.08.2010, 14:14
ну тогда проблемы как таковой нет — где плодим, там и следим за "исчезновением популяции" ;)
Psycho Tiger
24.08.2010, 14:27
bebop, не верно.
У Dictionary есть ключ weakKeys, по типу weakReference у EventDispatcher::addEventListener, который как раз указывает, учитывать ли GC эти ссылки, или не учитывать.
К тому же, простое зануление ссылки на объект не даёт гарантии того, что это дело удалится из памяти. Если использована чертовски высокая завязанность (например, когда есть объект а и объект б, у объекта а тыща ссылок на объект б, а у объекта б тыща ссылок на а, зануляем ссылки на а и на б, но не зануляем ссылки из а на б и из б на а) то GC вполне может запутаться и решить, что это дело чистить не надо. Это я к пользе методов "псевдодеструкторов".
В CASALib, как я понял, по destroy() удаляются все ссылки на объект только в тех объектах, которые сами имплементят интерфейс IDestroyable. Т.е. если пользоваться только CasaSprite, CasaMovieClip, CasaLoader, Interval, DestroyableEventDispatcher и иже с ними, то все будет волшебно!
Не, не будет, не помню точно уже почему, но destroy() удаляет не все ссылки.
Не, не будет, не помню точно уже почему, но destroy() удаляет не все ссылки.
У меня все удаляет :)
gloomyBrain
24.08.2010, 15:47
У меня все удаляет
ОК, поехали
package {
/**
* ...
* @author gloomyBrain
*/
public class LinkHolder {
private var _link:Object;
public function LinkHolder(link:Object) {
this._link = link;
}
public function get link():Object {
return this._link;
}
}
}
Как удалять будем? =)
Zebestov
24.08.2010, 16:11
Классный у тебя get — типа void ;)
А удаляется запросто:
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
public class Main extends Sprite
{
private var lh:LinkHolder;
private var someObj:Object;
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
this.someObj = { 'test':'go' };
this.lh = new LinkHolder(this.someObj);
stage.addEventListener(MouseEvent.CLICK, this.onClickHandler);
}
private function onClickHandler(e:MouseEvent):void
{
this.lh = null;
// запускаем GC и наблюдаем исчезновение
// экземпляра LinkHolder
}
}
}
Причем даже не надо запускать руками GC в профайлере — по клику счетчик экземпляров LinkHolder становится в ноль сразу.
gloomyBrain
24.08.2010, 16:14
@Zebestov
Понятно, что можно удалить ссылку на LinkHolder. Имелось ввиду удаление ссылки на link, не удаляя при этом LinkHolder
Zebestov
24.08.2010, 16:23
хм. а зачем это делать?
Имелось ввиду удаление ссылки на link, не удаляя при этом LinkHolder
Добавить destroy, а потом его вызвать.
package
{
/**
* ...
* @author gloomyBrain
* @mail CartoonRaccoon@gmail.com
*/
public class LinkHolder {
private var _link:Object;
public function LinkHolder(link:Object)
{
this._link = link;
}
public function destroy():void
{
this._link = null;
}
public function get link():Object
{
return this._link;
}
}
}
Или это вопрос с подвохом?
Zebestov
24.08.2010, 16:30
Конечно с подвохом ))) нафиг нужен класс с названием "holder", который должен верно хранить ссылку на объект, который мы у него за спиной хотим прибрать с помощью GC (дзявальски хихикая под покровом ночи)
gloomyBrain
24.08.2010, 16:36
Хм.. я вообще про то, что CASALib в принципе не может удалять все ссылки, до тех пор пока объект не IDestroyable.
Zebestov
24.08.2010, 16:48
если просто null-нуть ссылки на оба экземпляра (в любом порядке) — все исчезает по GC.
Хм.. я вообще про то, что CASALib в принципе не может удалять все ссылки, до тех пор пока объект не IDestroyable.
Не понимаю чего так расхваливать CASALib. От того, что мы создали объект и имлементили ему касалибовский IDestroyable, ссылки чудеснейшим образом не станут удаляться сами по себе. Точно также, ручками, нужно будет прописать в destroy методе, что мы собственно зануляем и уничтожаем.
С тем же успехом можно свой IDestroyable написать и смысл не изменится.
Буди что со экранными объектами автоматизировано их рекурсивное удаление из дисплейлиста и вызов в каждом destroy - так тоже, писать метод 5 минут. Но все остальные переменные класса все равно ручками занулять в destroy нужно.
Не понимаю чего так расхваливать CASALib. От того, что мы создали объект и имлементили ему касалибовский IDestroyable, ссылки чудеснейшим образом не станут удаляться сами по себе. Точно также, ручками, нужно будет прописать в destroy методе, что мы собственно зануляем и уничтожаем.
С тем же успехом можно свой IDestroyable написать и смысл не изменится.
Буди что со экранными объектами автоматизировано их рекурсивное удаление из дисплейлиста и вызов в каждом destroy - так тоже, писать метод 5 минут. Но все остальные переменные класса все равно ручками занулять в destroy нужно.
Destroyable отписывается от событий DestroyableEventDispatcher после вызова destroy. Или это тоже 5 минут писать?
Psycho Tiger
24.08.2010, 16:58
Вообще то да)
ну значит никаких проблем
gloomyBrain
24.08.2010, 18:08
Не понимаю чего так расхваливать CASALib
Я и не хотел этого. Более того, прекрасно обхожусь без нее и ей подобных библиотек, ибо при нормальном подходе польза от нее сомнительная
Но все остальные переменные класса все равно ручками занулять в destroy нужно
Не обязательно. Как уже заметил Zebestov - если нет ссылки на сам объект, то нет и ссылок на его свойства.
Psycho Tiger
24.08.2010, 18:18
Глум, я написал ведь. Если 2 объекта очень "сцепленны" может быть ситуация, в которой GC будет думать что ссылки на них остались.
Хотя, эту статью где про это рассказывалось читал очень давно. Может, сейчас дела обстоят лучше.
Zebestov
24.08.2010, 18:26
Psycho Tiger, только что проверил.
Немного измененный пример gloomyBrain:
package {
/**
* ...
* @author gloomyBrain
* @mail CartoonRaccoon@gmail.com
*/
public class LinkHolder {
private var _link:Object;
public function LinkHolder() {
}
public function set link(link:Object):void
{
this._link = link;
}
public function get link():Object {
return this._link;
}
}
}
при "перекрестном использовании":
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
public class Main extends Sprite
{
private var a:LinkHolder;
private var b:LinkHolder;
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
this.a = new LinkHolder();
this.b = new LinkHolder();
this.a.link = this.b;
this.b.link = this.a;
stage.addEventListener(MouseEvent.CLICK, this.onClickHandler);
}
private function onClickHandler(e:MouseEvent):void
{
this.a = null;
this.b = null;
// запускаем GC и наблюдаем исчезновение
// обоих экземпляров LinkHolder
}
}
}
не вызывает "зависания" экземпляров — GC разобрался =)
Psycho Tiger
24.08.2010, 18:47
Нет, суть не в этом. Я очень упрощенно сказал, на самом деле ссылок должно быть очень много друг-на друга и желательно больше, чем в 2 объектах. То есть 5 связанных классов, каждый с которым связан, причем больше, чем одной ссылкой.
Короче, ужасный код должен быть)
Zebestov
24.08.2010, 18:52
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
public class Main extends Sprite
{
private var a:LinkHolder;
private var b:LinkHolder;
private var c:LinkHolder;
private var d:LinkHolder;
private var e:LinkHolder;
private var f:LinkHolder;
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
this.a = new LinkHolder();
this.b = new LinkHolder();
this.c = new LinkHolder();
this.d = new LinkHolder();
this.e = new LinkHolder();
this.f = new LinkHolder();
this.a.link = this.d;
this.b.link = this.c;
this.c.link = this.f;
this.d.link = this.b;
this.e.link = this.a;
this.f.link = this.e;
stage.addEventListener(MouseEvent.CLICK, this.onClickHandler);
}
private function onClickHandler(e:MouseEvent):void
{
this.a = null;
this.b = null;
this.c = null;
this.d = null;
this.e = null;
this.f = null;
// запускаем GC и наблюдаем исчезновение
// всех 6 экземпляров LinkHolder
}
}
}
та шо ж такое =)
Алгоритму mark-and-sweep пофигу, что-есть перекрестные ссылки, хоть их мильён...
Только я вот не знаю, использует этот алгоритм флешплеер.
Psycho Tiger
24.08.2010, 19:16
Zebestov, а чем этот код отличается от предыдущего? a никак не связан с f. b никак не связан с d и так далее. У всех по одной ссылке.
И я повторюсь - я сам этого дела не тестил, просто давным-давно читал в статье. Это вполне могли уже пофиксить. А может автор статьи вруша. Я лишь донёс мысль, по которой стоило бы писать деструкторы с занулением переменных. Хотя бы ради перестраховки.
Zebestov
24.08.2010, 22:01
Есть такое...
Проверил для "все ссылаются на всех, включая себя" — GC непобедим =)
Количество ссылок всегда контролируемое. Мы же создаем их сами. И обнулять должны тоже сами.
Не совсем. Ваше творения (классы) могут расширять (extends) совсем другие люди.
Добавлено через 2 минуты
Как уже заметил Zebestov - если нет ссылки на сам объект, то нет и ссылок на его свойства.
Скорее всего его свойство окажется очередной ссылкой на другой объект. Отсутствие ссылки на объект, содержащий ссылки на другие объекты не означает, что нет других ссылок на свойства объекта (ссылки вне объекта тоже ссылаются на тот другой объект) Т.е. данное утверждение не имеет смысла.
UPD. Чтобы понятнее было. Ссылки на ссылку не существует. И ссылки на ссылку ссылки тоже. Есть только объект и некоторое количество ссылок на него.
gloomyBrain
25.08.2010, 01:05
@dimarik
Чтобы понятнее было
Да я как бы в курсе, спасибо =)
Имелся ввиду случай, когда доступ к свойствам можно получить только через объект
@zuxul
Алгоритму mark-and-sweep пофигу, что-есть перекрестные ссылки, хоть их мильён...
Только я вот не знаю, использует этот алгоритм флешплеер.
Насколько я помню, именно его и использует
Да... тему увели в сторону и я забыл о корнях проблемы =)
А можно подробней описать ситуацию, при которой на один объект есть неконтролируемое количество ссылок?
Кеш, например. Если есть объект в кеше, то возвращаем ссылку на него, иначе грузим в кеш.
Psycho Tiger
25.08.2010, 11:47
Robotex, можно поподробнее? Как грузить в кэш? Как узнать, есть ли объект в кэше?
Zebestov
25.08.2010, 13:51
Кеш, например. Если есть объект в кеше, то возвращаем ссылку на него, иначе грузим в кеш.
И где здесь "неконтролируемое количество ссылок"? Это кэш может не знать сколько ссылок и где они — но это и не его дело, по сути.
Кеш, например. Если есть объект в кеше, то возвращаем ссылку на него, иначе грузим в кеш.
Ух-ты ссылка на кэш прямо из области памяти флэш объекта? Это в какой операционной системе? Где вы это прочитали или додумали:D?
Количество инстанцирований объекта легко можно подсчитать статической переменной.
Работает на vBulletin ® версия 3.7.3. Copyright ©2000-2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Copyright © 1999-2008 Flasher.ru. All rights reserved.