Непреодолимый аппетит к CPU

3 views
Skip to first unread message

Roma Oskolkov

unread,
Sep 1, 2008, 11:25:57 AM9/1/08
to ruF...@googlegroups.com
Добрый вечер друзья,

Помогите пожалуйста советом.
Есть флэш ролик который загружает извне картинки и видео.
Картинки после загрузки переводятся в Битмапдату, а Loader'ы их загрузившие очищаются unload'om
В ролике также есть разделы, который берутся из бибилиотеки.

Так вот. Всякий раз запуская раздел (addChild) я замечаю как флэш плеер кушает примерно на 10-20 мегабайт больше памяти. Ростет до двух сотен и дальше.

Разумеется каждый раз при запуске нового раздела, предыдущий удаляется с помощью removeChild
Или этого недостаточно?

То-есть я понимаю что подгруженный с помощью Лоадера мувик надо удалять очень кривым способом (если не считать unloadAndStop).
Но мувики которые просто аттачатся из библиотеки. Как с ними быть?

Спасибо.



Ivan Dembicki

unread,
Sep 1, 2008, 11:38:29 AM9/1/08
to ruF...@googlegroups.com
Hello Roma,

> Разумеется каждый раз при запуске нового раздела, предыдущий удаляется с
> помощью removeChild
> Или этого недостаточно?

1. главное, чтобы ссылок не оставалось.
2. сразу память не очищается. Сборщик мусора срабатывает
позже, по собственной логике.

--
iv
http://www.bezier.ru
http://bezier.googlecode.com

noubase

unread,
Sep 1, 2008, 11:42:07 AM9/1/08
to ruF...@googlegroups.com
Ivan Dembicki написав(ла):

> 1. главное, чтобы ссылок не оставалось.
> 2. сразу память не очищается. Сборщик мусора срабатывает
> позже, по собственной логике.
>
>

Сборщик мусора запускается когда идет попытка выделения памяти под любой
новый объект, насколько я помню.

Roma Oskolkov

unread,
Sep 1, 2008, 11:45:46 AM9/1/08
to ruF...@googlegroups.com

> 1. главное, чтобы ссылок не оставалось.


Ссылок на удаляемый объект? Или надо удалять все ссылки внутри удаляемого объекта также?
Но это же можно свихнуться.

Flop Serg

unread,
Sep 1, 2008, 11:58:06 AM9/1/08
to ruF...@googlegroups.com
Картинки после загрузки переводятся в Битмапдату, а Loader'ы их загрузившие очищаются unload'om

вот это батенька вы зря... битмапдата занимает больше места в оперативке чем лоадер (проверено)
битмадата - это есть массив пикселов в 32(24) бита на пиксель, а лоадер всеже - картинку держит (жипег какойнить)

закралось у меня мусль что может у тя эти битмапдаты и отжытают память, чистить их не забывай принудительно на всякий случай
есть такая штука как bitmapData.dispose() - отчищает память

на всякий случай:
- не только де-аттачть но и остановть, отписать от событий, все сыллки приравнять к null (полностью умертвить)
- сборщик мусора можно вызвать принудительно ручками System.cg()

Ivan Dembicki

unread,
Sep 1, 2008, 11:58:06 AM9/1/08
to ruF...@googlegroups.com
Hello Roma,

> Ссылок на удаляемый объект?
- да.
и чтобы объект не был подписан
на события внешних объектов,
например stage.

Roma Oskolkov

unread,
Sep 1, 2008, 12:01:20 PM9/1/08
to ruF...@googlegroups.com
Flop, спасибо.

А если внутри удаляемого объекта есть объекты подписанные на stage, то и их удалять также по-отдельности перед удалением "родителя"?

Roma Oskolkov

unread,
Sep 1, 2008, 12:03:48 PM9/1/08
to ruF...@googlegroups.com
И то-есть, получается если какой-нибудь несчатный спрайт отрисовывает внутри себя БитмапДату, и потом мы этот спрайт удаляем, то БитмапДата так и остается в оперативе навсегда, если её не dispose()?

Nox Noctis

unread,
Sep 1, 2008, 12:16:42 PM9/1/08
to ruF...@googlegroups.com
> А если внутри удаляемого объекта есть объекты подписанные на stage, то и
> их удалять также по-отдельности перед удалением "родителя"?

у всего, что ты хочешь удалить
- не должно быть запущенных setTimeout() и setInterval()
- не должно быть запущенных таймеров
- не должно быть работающих онентерфреймов (даже если ты подписан на что-то
внутри удаляемого объекта)
- не должно быть ссылок на внешние объкты (и у внешних объектов, понятное
дело, не должно быть ссылок на что-то внутри удаляемого)

я лично во всех объектах, которые подразумевают динамическое создание и
удаление, прописываю метод destroy(), который сносит все ссылки не-примитивных
типов и все подписки.

чобы проверить, что все сделано правильно, можно сделать следующее:
- запуситься из-под флекс билдера в дебаг режиме и запустить gc
- или сделать в приложении кнопку, которая запустит System.gc() (проверять в
дебаговом плеере, разумеется)
- или использовать старый хак, который тоже приводит к принудительному запуску gc:
try {
new LocalConnection().connect("_gc");
new LocalConnection().connect("_gc");
} catch (error : *) {
}

-- если принудительно устроить запуск gc, то можно увидеть, чистится ли память
на самом деле, или нет.

--
Michael Antipin
______________________________________________________________________
n...@skazkastudio.ru | http://www.skazkastudio.ru

Flop Serg

unread,
Sep 1, 2008, 12:19:45 PM9/1/08
to ruF...@googlegroups.com



И то-есть, получается если какой-нибудь несчатный спрайт отрисовывает внутри себя БитмапДату, и потом мы этот спрайт удаляем, то БитмапДата так и остается в оперативе навсегда, если её не dispose()?



если ты сделал это сделал в одном методе и через локальные переменные (var) то ничего не надо
главно чтобы ссылок на битмапдату не осталось нигде например:

class Mimage extends Sprite{
....
function drawImage(loader:Loader):void {
  var bmd:BitmapData = new BitmapData(100,100);
  bmd.draw(loader);
  var bmp:Bitmap = new Bitmap(bmd);
  this.addChild(bmp);
}

и ненадо ничего по отдельности удалять
при удалении объекта класса Mimage битмапдата почистится
хорошо чтобы где у тебя упоминались ссылки на объект этого класса они приравнялись к null ( mimageImstance = null )

а еще отписать от событий например стэйджа например в отдельном методе mimageImstance.destroy()

class Mimage extends Sprite{
....
function destroy():void {
 this.removeEventListener(Event.ENTER_FRAME,onEnterFrame)
 my_interval.stop();
 my_timeline.stop()
}




Roma Oskolkov

unread,
Sep 1, 2008, 12:35:20 PM9/1/08
to ruF...@googlegroups.com
Спасибо большое всем!


"destroy(), который сносит все ссылки не-примитивных
типов и все подписки."

А есть какой-то простой способ снести все подписки сразу?
Чтоб не вручную удалять по отдельности.

Valentin Simonov

unread,
Sep 1, 2008, 2:57:20 PM9/1/08
to ruF...@googlegroups.com
Ссылок на загруженный обьект и обработчиков событий привязанных на
функции этого обьекта. Разумеется, предполагается, что ссылки на
внутренние подобьекты нигде не создаются. Плюс насколько я знаю
unload() не помогает. И, само собой битмапы надо клонировать а не
обращаться напрямую, чтобы избежать ненужных ссылок.

Sent from my iPhone

Roma Oskolkov

unread,
Sep 1, 2008, 3:11:57 PM9/1/08
to ruF...@googlegroups.com
Вопрос немного не в тему, но всё же ― а в AS2 старый-добрый removeMovieClip тоже ничего по сути не удалял?
Кажется он вырезал всё подчистую, ибо не помню я таких мемориликов как сейчас.

Ivan Dembicki

unread,
Sep 2, 2008, 5:28:50 AM9/2/08
to ruF...@googlegroups.com
Hello Roma,

> а в AS2 старый-добрый removeMovieClip
> тоже ничего по сути не удалял?

- сам объект-мувиклип не удалялся (если
оставалась на него ссылка), рекурсивно
удалялись дочерние мувики, а также любое
содержимое. Также у мувика сносились
служебные линки на прототипы, конструктор
и т.п.

Что касается твоего основного вопроса
и поиска универсального решения.
По идее оно есть - использование
weekReference - мягких ссылок при
подписывании на событие.
В этом случае тебе можно не заботиться
об отписке. Точнее не всегда заботиться:
высоконагруженные операции и часто
вызываемые события всё равно нужно
сносить руками. Такие как onEnterFrame.

Но, с моей точки зрения, использование
weekReference - нехороший признак,
сигнализирующий, что автор кода либо
лентяй откровенный, либо, что еще хуже
не понимает сути происходящего у него
в коде.

Более приемлемое решение использовать
события addedToStage и removedFromStage
При добавлении на сцену подписывать всё
что нужно, при удалении отписывать.
Но и к этому не следует подходить как
к универсальному решению: это лишь
часть потока исполнения программы,
лишь удобные точки для отслеживания,
но не единственные и не всегда идеально
подходящие.

Roma Oskolkov

unread,
Sep 2, 2008, 5:46:27 AM9/2/08
to ruF...@googlegroups.com
А что такое weekReference?

Nox Noctis

unread,
Sep 2, 2008, 5:56:58 AM9/2/08
to ruF...@googlegroups.com
Roma Oskolkov пишет:
> А что такое weekReference?

Еженедельный журнал по программированию на АС. :)

http://www.google.ru/search?q=ActionScript+weakReference

mike

unread,
Sep 8, 2008, 2:14:47 AM9/8/08
to ruFlash
Посмотреть, что происходит внутри Flex/Flash приложения можно с
помощью флексового профайлера. Все объекты с ссылками будут как на
ладошке.

Roma Oskolkov

unread,
Sep 8, 2008, 4:45:56 AM9/8/08
to ruF...@googlegroups.com
Кстати, удалось справится с этим чудовищным мемориликом.
В связи с чем хочу выразить всем откликнувшимся благодарность.

Ко всем листенерам что не убивались вручную, я добавил weakReference
А также ко всем динамическим классам, по совету Нокса, прикрутил destroy срабатывающий на REMOVED_FROM_STAGE
А также прикрутил работающий таймер который раз в энное время смотрит System.totalMemory и если она более 35mb, включается System.gc();

Теперь вместо {50-200;+∞} mb  флешка кушает 20-40.

denis.sh...@gmail.com

unread,
Sep 8, 2008, 4:59:32 AM9/8/08
to Roma Oskolkov

> А также прикрутил работающий таймер который раз в энное время
> смотрит System.totalMemory и если она более 35mb, включается System.gc();

System.gc() замечательная штука но она работает только в дебаг плеере.


--
Denis Sheremetov

Roma Oskolkov

unread,
Sep 8, 2008, 5:10:15 AM9/8/08
to ruF...@googlegroups.com
Точно?
Отчего-то я замечал очень характерную закономерность что после вызова этой штуки память реально сбавляла в весе существенно.

denis.sh...@gmail.com

unread,
Sep 8, 2008, 5:26:08 AM9/8/08
to Roma Oskolkov
> Точно?
> Отчего-то я замечал очень характерную закономерность что после
> вызова этой штуки память реально сбавляла в весе существенно.

Конечно, у тебя же debug version плеера со standalone этого не будет.

--
Denis Sheremetov

Reply all
Reply to author
Forward
0 new messages