Главная ReadMe F.A.Q. Регистрация Форум




Сколько вам лет?
10-15
15-18
18-22
22-27
27-35
35-40
40-60
Система Orphus
Популярные новости!
» flash урок: Анимация - за час создаем свой персона ...
» flash помощь: Какой код у этой клавиши?
» flash журнал скоро!
» Идея проекта
» Браузерная flash игра (этап 1): Движек игры боевки
Случайные новости!
» flash помощь: Какой код у этой клавиши?
» flash игра: Steppenwolf. Эпизоды 1-4.
» flash урок: Создание прокручиваемого текстового по ...
» flash demo: 3D Sony Ericsson - можно вращать и наж ...
» flash игра: Grow Cube, Grow Island, Grow RPG - кла ...
» программа: SWiSH Max 2
» flash демо: Робот, который ходит :)
Архив
Июнь 2009 (21)
Май 2009 (18)
Апрель 2009 (15)
Март 2009 (24)
Февраль 2009 (23)
Январь 2009 (14)


Внимание! У Вас появился шанс изучить все секреты Flash анимации! Перейти из разряда новичка в разряд опытного пользователя даже без посещения дорогих репетиторов и толстенных толмутов "библий пользователя".

Более 100 уроков записанных с экрана компьютера в превосходном качестве помогут пройти, Вам, терни Flash анимации кратчайшим путём!

Подробнее!..

www.webmoney.ru

actionscript 3.0: Работа с памятью

28 апреля 2009

Автор: Павел Наказенко (DTF.RU)


Студент Сибирского государственного Аэрокосмического Университета им. академика М. Ф. Решетнева, факультет информатики и систем управления. Лауреат премии талантливой молодежи, призер всероссийского конкурса по компьютерной графике. Занимался фрилансом (программирование), работал над рядом игровых проектов, в том числе над игрой «Воплощение». В настоящий момент — программист компании «Стратегикон».


0. Введение или «зачем все это?»


В настоящее время сфера online-игр изобилует продуктами, использующими технологию Flash: будь то различные мини-игры или крупные online-проекты (например, браузерные MMORPG). Причем, стоит обратить внимание на тот факт, что Flash приложения авторы стараются использовать по минимуму в своих игровых разработках, отводя им чисто иллюстративную роль. Работая над «Воплощением» мне показался странным тот факт, что несмотря на возможности доступных сред и SDK (Flex, Flash CS, Flash Developer, IDEA), можно было сосчитать по пальцам крупные flash-based бизнес приложения и игры. Как оказалось позже, на то были объективные причины.


Во-первых, приложения базирующиеся на Flex SDK имеют очень низкую производительность в плане визуализации, однако предоставляют довольно удобный набор компонент для быстрого создания бизнес-приложений. В свою очередь, Flash CS SDK обладает высокой производительностью в плане визуализации, однако предоставляет довольно бедный набор визуальных компонент. Существуют различные хитрости и методы оптимизации процесса визуализации Flex SDK приложений, однако их описания не будет в рамках данной статьи.


Во-вторых, сопроводительная документация к любому SDK от Adobe оставляет желать лучшего: часть важных и полезных функций не документирована, практически отсутствуют рекомендации по оптимизации приложений и описание работы базовых механизмов Flash Player (вроде Renderer’а и GC), низка активность представителей Adobe на issue-related форумах. Большую часть информации приходилось добывать из различных блогов и на независимых web-ресурсах. И это не говоря уже о большом количестве ошибок в SDK, которые иногда получается устранить с помощью создания своего исправленного класса — наследника родителя с ошибкой.


В-третьих, темпы обновлений от Adobe сложно предугадать, равно как и масштабы изменений с каждой новой субверсией. Опять же, порой с новой субверсией возникали различные конфликты: начиная от несовместимости Flash Player с семейством ОС, заканчивая отсутствием обратной совместимости с предыдущими субверсиями (спасает только принудительное требование последней версии при открытии страницы с приложением).


В-четвертых, было потрачено довольно много времени на поиск Flash Player для *bsd и *nix семейств, но найти версию, корректно работающую с кириллицей (проблема отображения ввода с клавиатуры), так и не удалось. Не помогло даже использование Wine, как и различные хитрые манипуляции с локалями и переменными окружения целевой ОС.


Вышеперечисленные причины — далеко не все трудности, с которыми приходится сталкиваться разработчику крупных Flash приложений. Однако подобное положение вещей — довольно частое явление среди относительно молодых технологий. Среди прочих хотелось бы отметить самую важную, на мой взгляд, проблему: отсутствие документации по работе с памятью.


Дело в том, что после старта клиента игры «Воплощение» на машинах пользователей наблюдался сильный перерасход памяти, а, следовательно, снижение производительности системы в целом, не говоря уже о зависаниях браузера. Что интересно, график расхода памяти Windows показывал резкие скачки, что не двусмысленно намекало на «не обычную» работу GC Flash Player.


Данная статья является своеобразным сводом правил по работе с памятью в приложениях на основе ActionScript 3. Прежде всего, хотелось бы уточнить, что данные, описанные в статье, собирались по крупицам из Интернета, некоторые из них являются следствием горького опыта. Полноценной документации по работе с памятью от производителя нет. По причине отсутствия целостного описания простейших правил работы с памятью даже опытные разработчики часто сталкиваются с проблемой утечки памяти или ее необоснованного перерасхода. К сожалению, количество «подводных камней» велико, и на поздней стадии разработки может потребоваться довольно много ресурсов для внесения необходимых исправлений.


Предполагается, что читатель владеет базовыми навыками программирования на языке ActionScript 3.


1. Термины и определения


Прежде чем начать описание базовых правил работы с памятью, условимся, что:


Garbage Collector (GC) — это механизм, который в определенные моменты времени пытается освободить память, использованную объектами, которые уже не будут востребованы приложением (то есть производит сборку мусора).


Strong reference — обычный тип ссылки на объект, наличие которого сигнализирует GC об актуальности и необходимости объекта.


Weak reference — обособленный, «не строгий» тип ссылки на объект, наличие которого не влияет на работу GC.


Chunk (чанк) — в нашем случае некоторое количество байт, выделенное менеджером памяти для объекта по требованию Flash Player.


Pool (пул) — в нашем случае совокупность определенного количества чанков.


2. Принципы работы Garbage Collector


Память, которой оперирует GC, представлена в виде пулов, которые, в свою очередь, представлены набором чанков по несколько байт (обычно 512). Такие крупные объекты как картинки и файлы в пул не заносятся.


По запросу на выделение памяти резервируются некоторое количество чанков. Как только свободных чанков становится недостаточно, выделяется новый пул. По мере того, как объект удаляется или явно теряет свою актуальность, соответствующий ему chunk памяти помечается как «unused», но фактического освобождения памяти не происходит. При этом GC совершает итерацию по текущему пулу памяти. В том случае, если памяти становится мало, GC пытается освободить память из-под «unused» чанков, но делает это только в пределах текущего пула. В том случае, если этого оказывается не достаточно, совершается дополнительная итерация по дефрагментации пулов, то есть упорядочиванию «unused» чанков среди остальных пулов для последующего освобождения памяти.


Однако не существует гарантии, что за одну итерацию будут освобождены все неиспользованные чанки. Объекты, которые имеют счетчик строгих ссылок больше нуля, не удаляются GC. Поэтому зачастую GC выделяет пул, когда есть возможность использования «unused» чанков. Из-за этого возникает сильная фрагментация пулов (необоснованный перерасход памяти) и утечки памяти.


Специфической чертой работы GC в AS3 является то, что не производится периодической проверки на наличие «мусора». Это означает, что выделение памяти будет оставаться на том же уровне, несмотря на многочасовой idle приложения или при микрооперациях с памятью, когда для GC не возникает необходимости очищать пул или создавать новый (совершать итерацию).


3. Weak References, Strong References


Как уже было сказано ранее, все ссылки в Action Script 3 делятся на два вида: weak references и strong references. Единственное различие между ними — Garbage Collector при удалении объекта не обращает внимания на weak references, в то время как, если счетчик strong references > 0, то память не освобождается.


4. Правила работы со ссылками


4.1. Все strong-ссылки на объекты в ActionScript должны удаляться, в противном случае GC удалением подобных объектов не занимается.


Пример:


// Создаем объект, помещаем референс на него в first
var first:Object = {dtf:"rulez"}
// помещаем референс в second
var second:Object = first;
// удаляем объект first
delete(first);
// смотрим, сохранился ли объект в памяти
trace(second.dtf);
// выведет "rulez", значит память все еще не освобождена

Варианты решения:



  1. Слежение за strong reference вручную, своевременное их удаление. Требует больших трудозатрат.

  2. Использование WeakReference (см. ниже). Сравнительно небольшие трудозатраты в использовании.


4.2. Необходимо стараться не допускать циркулярных связей, так как в таком случае объект почти гарантированно не будет выгружен из памяти.


Пример (стараться избегать):


var first:Object = {}
// создаем объект со ссылкой на первый
var second:Object = {link: first};
// у первого объекта делаем ссылку на второй
first.link = second;
// пытаемся удалить оба референса
delete(first);
delete(second);
// при этом доступ к объектам first и second мы теряем, однако счетчик
референсов у каждого из них все еще равен 1

Примечание: Специфично для различных версий Flash Player 8.x, 9.x. В некоторых Mark Sweeping алгоритм справляется, в некоторых нет.


Варианты решения: Использовать WeakReference (см. ниже).


4.3. События, назначаемые объекту, обязательно должны иметь флаг weakReference.


Пример:


Неправильно:


object.addEventListener(Event.CLICK,handleClick); 

Правильно:


object.addEventListener(Event.CLICK,handleClick false,0,true); 

Такая необходимость обусловлена тем, что хэндлеры по умолчанию считаются как strong reference для объекта, даже если он уже удален.


Примечание: Рекомендуется так же контролировать удаление назначенных Listener’ов с помощью парной функции removeEventListener();


4.4. При использовании словарей (Dictionary) необходимо использовать опцию weakKeys в конструкторе, где это уместно.


Пример:


var dict:Dictionary = new Dictionary(true);
dict[firstObj] = secondObj;
// при этом, на firstObj у словаря weak reference, а на secondObj – strong reference

4.5. Предпочтительно использование класса WeakReference при работе со сложными, большими объектами.


На основе возможностей использования weakKeys у словаря (пункт 2.4), можно написать класс, обеспечивающий «не строгие» ссылки на объекты.


Пример:


i
mport utils.WeakReference;
function getWR(data):WeakReference {
return new WeakReference(data);
}
...
function doSome(object:BigComplexObject):void
{
// получаем weak ссылку на объект
var weakBigObject:BigComplexObject = getWR(object).get() as
BigComplexObject;
// работаем как с обычным объектом
weakBigObject.Run();
}

Примечание: WeakReference не является стандартным модулем. Скачать WeakReference.as (610 байт).


5. Memory Controller


Ввиду особенностей работы GarbageCollector в ActionScript 3 рекомендуется использовать класс MemoryController для регулярного совершения GС итераций и освобождения памяти. Не рекомендуется использовать одновременно более одной копии MemoryController в приложении.


Пример использования:


import utils.MemoryController
...
private var mMemoryController:MemoryController;
...
mMemoryController = new MemoryController(<интервал обновления>, <лимит расхода памяти
в байтах перед принудительным совершением итерации GC>, <лимит расхода памяти перед
критичной ситуацией>, <мин. интервал между принудительными итерациями>, <количество
принудительных итераций за раз>, <хэндлер, вызываемый при прохождении критического
предела>, <хэндлер, вызываемый при прохождении опасного предела>);

Данный класс в соответствии с указанным интервалом обновления производит выделения/освобождения памяти различного размера, дабы задействовать максимально возможное количество «unused» чанков в пределах текущего пула или спровоцировать спонтанную итерацию по всем пулам. Как только приложение пересекает «опасный» лимит памяти, MemoryController начинает форсировать заданное количество итераций GC с минимальным интервалом между попытками (указано внутри конструктора класса). Так же вызывается соответствующий хэндлер, если это указано (может быть использовано для отладки или дополнительной информации). По мере того, как приложение достигает «критического» уровня выделения памяти, вызывается соответствующий хэндлер, попытки форсированных итераций продолжаются.


Конечно, такой способ не является панацеей. Но как показала практика, использование такого подхода к работе с GC не нагружает CPU, но позволяет более рационально использовать выделенную память и снизить фрагментацию пулов.


Не рекомендуется выставлять короткий слишком интервал между попытками форсирования итерации GC или выставлять большое количество этих самых итераций, так как это может серьезно снизить производительность приложения.


Примечание: MemoryController не является стандартным модулем. Скачать MemoryController.as (3278 байт).


6. Заключение


Применив в коде «Воплощения» несколько правил из раздела 4, а так же MemoryController, получилось существенно снизить объемы утечки памяти: с пика перерасхода в более чем 220 Мбайт, до 85–95 Мбайт.


Применение всех выше перечисленных базовых правил и вспомогательных средств на начальном этапе разработки позволяет повысить производительность приложения в целом и избежать сильного перерасхода памяти. Описанные методики могут быть использованы так же и на поздней стадии разработки проекта, однако исправление кода в этом случае может потребовать некоторых ресурсов. Ввиду разнообразия SDK для разработки flash-приложений, в данной статье приведены лишь общие правила и не рассмотрено поведение отдельных компонентов Flex SDK и Flash CS SDK, многие из которых изначально содержат ошибки, ведущие к утечкам памяти.

Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь. Мы рекомендуем Вам зарегистрироваться либо зайти на сайт под своим именем.

Другие новости по теме:

  • Actionscript: События Мыши и Обработчики Событий в Adobe Flash. Уроки Actio ...
  • flash уроки: «Азы ActionScript. Часть 2» (Скачать Бесплатно). Уроки Action ...
  • новости: Глава Opera уверен, что HTML 5 оттеснит технологию Adobe Flash
  • новости: очередной "убийца" Adobe Flash
  • 19 способов повысить производительность actionscript 3.0 приложений



  •  (голосов: 2)
    Aloran | Просмотров:825 | Напечатать
    #1 написал: Aloran (29 апреля 2009 15:34)


    Группа: Журналисты
    Регистрация: 6.03.2009
    Комментариев: 74
    Публикаций: 10
    Россия, Ульяновск
    в пункте 4.3 в строке
    object.addEventListener(Event.CLICK,handleClick false,0,true);
    добавте запятую. Должно получиться так
    object.addEventListener(Event.CLICK,handleClick, false,0,true);


    --------------------
    Учитель достается тому, кто его достает!
    ICQ: --
    Информация
    Посетители, находящиеся в группе Гости, не могут оставлять комментарии в данной новости.
    Видео Журнал "Легко о Flash" - подписавшись на него вы будете один раз в месяц получать его выпуск на свой почтовый ящик, там вы найдете новые видео уроки по работе в программе Adobe Flash CS4.

    Ваш e-mail:

    Ваше имя на русском:
    политика антиспама
    подпишитесь сейчас и получите доступ ко всем выпущенным журналам
    Логин
    Пароль
     


    Требуется для просмотраFlash Player 9 или выше.

    Показать все теги


    Rambler's Top100 Рейтинг@Mail.ru Rating All.BY Каталог SiteCreation rate your site
    links
    Internet Map page counter