2010-06-01 2 views
1

У меня возникли проблемы с управлением памятью во флэш-приложении. Использование памяти растет довольно много, и я отследил ее до того, как я загружаю активы.Использование памяти во Flash/Flex/AS3

я вставлять несколько растровых изображений в классе Embedded, как этот

[Embed(source="/home/gabriel/text_hard.jpg")] 
public static var ASSET_text_hard_DOT_jpg : Class; 

я экземпляр Активов, таким образом

var pClass : Class = Embedded[sResource] as Class; 
return new pClass() as Bitmap; 

На данный момент, использование памяти идет вверх, что является совершенно нормальным , Однако null все ссылки на объект не освобождают память.

Основываясь на этом поведении, похоже, что флеш-плеер создает экземпляр класса при первом запросе, но никогда не выпускает его - не без ссылок, вызывая System.gc(), делая двойной трюк LocalConnection , или вызов dispose() в объектах BitmapData.

Конечно, это очень нежелательно - использование памяти будет расти до тех пор, пока все в SWF-файлах не будет установлено, независимо от того, давно ли я давно перестал использовать какой-то актив.

Является ли мой анализ правильным? Можно ли что-то сделать, чтобы исправить это?

ответ

0

Оказалось, что я поддерживаю ссылки на объекты, которые не выгружаются. Очень сложно. GC работает правильно во всех описанных случаях, которые, как я подозревал, могут быть разными.

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

0

Почему вы хотите использовать это?

var pClass : Class = Embedded[sResource] as Class; 
return new pClass() as Bitmap; 

Иногда динамическое назначение ресурсов является ошибкой и не может быть освобождено. У меня были подобные проблемы, прежде чем с флеш-плеером и flex, например. загружая и выгружая одну и ту же внешнюю swf ... память постоянно увеличивалась с размером загруженного swf, даже если я вызывал system.gc(); после разгрузки swf.

Так что я предлагаю пропустить этот подход и использовать первый описанный вами случай.


UPDATE 1

<?xml version="1.0" encoding="utf-8"?> 
<s:Application 
    xmlns:fx   = "http://ns.adobe.com/mxml/2009" 
    xmlns:s   = "library://ns.adobe.com/flex/spark" 
    xmlns:mx   = "library://ns.adobe.com/flex/mx" 
    creationComplete = "creationComplete()"> 

<fx:Script> 
    <![CDATA[ 



     [Embed(source="/assets/logo1w.png")] 
     private static var asset1:Class; 

     [Embed(source="/assets/060110sinkhole.jpg")] 
     private static var asset2:Class; 


     private static var _dict:Dictionary = new Dictionary(); 

     private static function initDictionary():void 
     { 
      _dict["/assets/logo1w.png"] = asset1; 
      _dict["/assets/060110sinkhole.jpg"] = asset2; 
     } 

     public static function getAssetClass(assetPath:String):Class 
     { 
      // if the asset is already in the dictionary then just return it 
      if(_dict[assetPath] != null) 
      { 
       return _dict[assetPath] as Class; 
      } 

      return null; 
     } 

     private function creationComplete():void 
     { 
      initDictionary(); 
      var asset1:Class = getAssetClass("/assets/logo1w.png"); 
      var asset2:Class = getAssetClass("/assets/060110sinkhole.jpg"); 
      var asset3:Class = getAssetClass("/assets/logo1w.png"); 
      var asset4:Class = getAssetClass("/assets/060110sinkhole.jpg"); 
      var asset5:Class = getAssetClass("/assets/logo1w.png"); 
     } 
    ]]> 
</fx:Script> 

+1

Извините, я не совсем понимаю. Я описал только один способ сделать это. Первый фрагмент показывает, как я вставляю активы, а второй - как я их пример. Вы имеете в виду, почему я просто не делаю 'new ASSET_text_hard_DOT_jpg()'? Это потому, что мой код довольно сложный и не всегда знает заранее, что ему нужно, например, он создает строку из нескольких частей и получает изображение с именем (т.е. «text_» + s_lDifficulty [nDifficulty] -> «text_hard») – ggambett

+0

I извините, но я думаю, что вещь, которую вы пытаетесь достичь, невозможна. Из того, что я знаю, ресурсы встроены, когда swf построен, я не уверен, что вы можете динамически встраивать ресурс, как вы описали. Что бы я сделал, чтобы создать словарь и поставить туда все необходимые мне ресурсы. Я бы использовал его, как в коде UPDATE1, который я написал сейчас в ответе. –

1

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

Кроме того, поскольку вы используете встроенный, а не загруженный актив, фактические данные могут быть недоступны. Поскольку это часть вашего SWF, я бы сказал, что вы можете разумно ожидать, что он будет в памяти на всю жизнь вашего SWF.

0

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

Это также совершенно нормально. Редко для любой системы гарантировать, что момент прекращения ссылки на объект в коде - это тот же самый момент, когда память для него возвращается в операционную систему. Именно поэтому существуют такие методы, как System.gc(), чтобы вы могли принудительно очистить их, когда вам это нужно. Обычно приложение может реализовать некоторый пул, чтобы поддерживать объекты и память в целях эффективности (поскольку распределение памяти обычно медленное).И даже если приложение действительно вернет память в операционную систему, ОС может по-прежнему считать ее назначенной для приложения на некоторое время, в случае, если приложение должно будет запросить несколько позже.

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

Смежные вопросы