На DTF.ru по наводке Imugi нашлась статья Павла Наказненко с описанием работы Garbage Collector для ActionScript 3, возникающих при этом трудностей и путей их преодоления.
Автор не ограничивается описанием решения проблем, но также прикрепляет к статье два класса. Это утилиты, которые, по словам Павла, позволили ему безопасно снизить расходование памяти с 200 до 95 Мб для флэш-игры "Воплощение". Более, чем в два раза — это немало. Файлы:
WeakReference.as: класс для смягчения ссылок на объекты. Как вы наверняка знаете, сборщик мусора может утилизировать объекты, на которые нет сильных ссылок. Класс напоминает аналогичный от Гранта Скиннера, но тут есть комментарии на русском.
WeakReference.as
MemoryController.as: класс централизованного управления хаком для форсирования сборки мусора (хак типа "двойной LocalConnection"). Этот класс — неплохой пример превращения хака в законное решение решение. У данного контроллера памяти есть настраиваемые параметры, такие, как максимально допустимый / критический объем занимаемой приложением памяти, временной интервал между принудительными очистками памяти и т.п. Непонятным для меня осталось назначение метода doSimpleClean в этом классе — есть мысли?
MemoryController.as
doSimpleClean
хак типа "двойной LocalConnection"
что такое gc понимаю, как работает понимаю, что такое weak reference тоже. но как это может помочь безопасно снизить расходование памяти с 200 до 95 Мб. это то weak reference безопасно? с геттером возвращающим Object (типа к черту типизацию)! System.totalMemory которая используется для мониторинга памяти показывает количество памяти съеденное всеми флеш-программами внутри этого процесса (читай внутри браузера), то есть, если человек играющий в их игру в новой вкладке откроет что-нибудь такое эдакое дизайнером написанное, 500 мегабайт кушающее, а критическое значение будет выставлено как раз в 500 мб тут начнёт срабатывать этот чудо-гц-хак (раз в секунду по умолочанию) рассчитывая, что тут у нас везде weak reference и будет он срабатывать пока юзер не закроет кривую флешку, работать с приложением естественно будет невозможно. и поправьте меня, если я ошибаюсь но System.totalMemory вроде бы показывает разные значения в разных средах.
*смотрит на код* хм, где-то я такое уже видел. *тут я раскуриваю трубку и водя увеличительным стеклом применяю метод SherlockHolmes.deduction()* судя по буковкам m и колбэкам вместо событий, автор флешерствует после msvc, а виндузятники как правило тяжело переносят расставание с любимым инструментом и привычками. не хватает контроля над памятью из сей, ох как не хватает, надо бы что-то придумать... но это все конечно мои предположения, прошу прощения, если кого-то обидел.
в биореактор
kutu182, System.gc() работает только в debug версии.
Думаю, что doSimpleClean пытается наворотить парочку лишних переменных в надежде, чтобы ГК сам включиться ;-).
doSimpleClean() -мне кажется как спусковой крючок, инициирует работу GC дефолтовым способом.
видел я эту с.-пупер статью. . сразу как захотел перелезть на AS стал интересоваться GC. А с ним-то тут полный писец >). Поправьте меня если я не прав ) )) Читал комменты каких-то неизвестных знатаков .. типа: "Ребята просто не разобрались с работой GC". А как же с ним разобраться, если в оффициальной литературе пишут что GC просто замечательно сам отрабатывает. Вобщем было бы неплохо увидеть все-таки профессиональные подходы к решению проблемы.
вик-референс это конечно хорошо, но этого недостаточно((. В нашем приложении > 500 классов, использование памяти неуклонно растет, хак очищает не больше 2-4 мегабайт. Бывало умирал ФФ набрав под 800 мегабайт - жесть. Все листенеры проверены, куда копать непонятно.
doSimpleClean наверное нужен для заполнения пула чанков. А в то же время
В том случае, если памяти становится мало, GC пытается освободить память из-под «unused» чанков, но делает это только в пределах текущего пула.
куда копать непонятно
500 классов
да этого достаточно. профайлер пробовал, вырезать, отключать методы классы, очищать память с хаком или через gc(), оставался один каркас от класса - пустышка даже без полей и она через раз не собиралась ни в какую, сколько бы не ходил по прилаге, не ждал, хотя ссылок на него уже нигде не было.
как профайлить такой случай? ну видно - не собирается, а почему? класс-то пустой
Я ратую за жёсткий подход к ссылкам, в том числе, и при добавлении слушателей. Weak reference - для ситуаций, когда владелец кода не понимает этого кода или не хочет понимать, в частности, если код достался по наследству от какого-нибудь разгильдяя. И то, как временное решение only.
когда владелец кода не понимает этого кода или не хочет понимать
2 Alexander. хм... тяжело чтото сказать. но если б все было так плохо - эти проблемы появлялись бы у всех. может профайлер глючит.. 600М - жесть для сравнительно маленькой апп..
ладно оставим это, жалобы на гц есть - факт, не у всех они становятся проблемой.
Куда еще можно посмотреть, я смог заметить только одну закономерность, если данных для таблиц не приходит - все собирается более менее. Рендеры не сложные используются компонет флекслиба СуперТаб и СперИмейдж. Что касается имейджа(под подозрением) - очистка кэша и гц потом не освобождают память - он бажный?
Alexander, ты имеешь в виду SuperImage от Ely Greenfield?
да, это он
600М - жесть для сравнительно маленькой апп..
Можно сделать аппликуху из одного класса которая сожрёт всю память, какая есть и попросит добавку.
var tf = addChild (new TextField()); var a = []; addEventListener(Event.ENTER_FRAME, function(e) { tf.text = System.totalMemory; a.push(new BitmapData(2880,2880)); });
А что, количество классов и занимаемая память как-то коррелируют?
if (System.totalMemory > mWarningMemoryLimit) { doForcedClean(); if (mWarningFunction) mWarningFunction(); } else if (System.totalMemory > mCriticalMemoryLimit) { if (mAbortFunction) mAbortFunction(); doForcedClean(); }
наверное надо поменять местами.
В реальной жизни да.