2013-10-07 3 views
0

Для того чтобы предотвратить утечку памяти в ActionScript 3.0, я использовать вектор члена в классах, которые должны работать с векторами, например:Как избежать утечек памяти в этом случае?

public class A 
{ 
    private var mHelperPointVector:Vector.<Point> = new Vector.<Point>(); 


    public static GetFirstData():Vector.<Point> 
    { 
     mHelperPointVector.length = 0; 
     .... 
     return mHelperPointVector; 
    } 


    public static GetSecondData():Vector.<Point> 
    { 
     mHelperPointVector.length = 0; 
     .... 
     return mHelperPointVector; 
    } 
} 

, а затем у меня есть потребители, которые используют GetFirstData и GetSecondData методу, хранящие ссылки к векторам, возвращаемые этими методами, например:

public function OnEnterFrame():void 
{ 
    var vector:Vector.<Point> = A.GetSecondData(); 
    .... 
} 

Этот трюк вроде бы хорошо, но иногда мне нужно обработать вектор возвращенное GetSecondData() после некоторого периода времени, и в этом случае, этот вектор перезаписывается другим вызовом GetSecondData() или GetFirstData() ... Решение заключается в том, чтобы скопировать вектор в новый вектор ... но в этом случае лучше избегать этого трюка вообще. Как вы справляетесь с этими проблемами? Я должен работать с большим количеством векторов (каждая из которых длится от 1 до 10).

+0

Два вектора размера 10 не должны быть проблемой. Я представляю себе проблему с распределением/созданием новых векторов и заполнением их значениями, но хотелось бы, чтобы узнать наверняка больше кода (базового рабочего образца для тестирования). Как идея, когда вы делаете GetFirstData, ваш класс A может иметь логический флаг, чтобы проверить, должно ли оно очищать предыдущие данные или нет. Кроме того, вид не по теме, посмотрите на пулы объектов. –

ответ

1

Дело в сборке мусора просто пытается избежать создания экземпляров (и удаления) в максимально возможной степени. Трудно сказать, какой будет лучший подход, поскольку я не могу понять, как/почему вы используете данные Vector, но на первый взгляд я думаю, что с вашим подходом вы будете постоянно терять данные (вы в значительной степени создавая эквивалент слабых экземпляров, так как они могут быть легко перезаписаны), и изменение длины вектора на самом деле не позволяет избежать сбора мусора (это может задержать и уменьшить его, но вы все равно постоянно бросаете данные).

Я откровенно не думаю, что у вас были бы утечки памяти с помощью векторов, если вы не пропустите ссылку на Вектор влево и вправо. В этом случае было бы лучше исправить эти оставшиеся ссылки, а не просто придумать решение для повторного использования одних и тех же векторов (что может иметь гораздо больше неблагоприятных эффектов).

Однако, если вы действительно обеспокоены памятью, ваше лучшее решение, я думаю, либо создает все необходимые вам векторы (если это фиксированный номер и вы знаете их длину раньше времени), либо, еще лучше, используя Object Pools. Последнее, безусловно, будет более надежным решением, но для его завершения требуется определенная настройка, создавая класс пула, а затем при его использовании. Для того, чтобы поместить его в код, после реализации, он будет использоваться как это:

// Need a vector with length of 9 
var myVector:Vector.<Point> = VectorPool.get(9); 

// Use the vector for stuff 
... 

// Vector not needed anymore, put it back in the pool 
VectorPool.put(myVector); 
myVector = null; // just so it's clear we can't use it anymore 

VectorPool будет контролировать список векторов у вас есть, позволяя другие части вашего кода «заимствовать» векторы по мере необходимости (в которых они были бы быть помечены как «используемые» внутри VectorPool) и вернуть их (помечая их как неиспользуемые). Ваш код также может создавать векторы на месте (внутри get()), если необходимо, если в списке неиспользуемых объектов нет доступных векторов; это сделает его более гибким (в некоторых случаях это не рекомендуется, так как вы все еще тратите время на создание экземпляра, но в данном случае, вероятно, незначительны).

Это очень макросообщение (вам все равно придется писать VectorPool), но пулы объектов, подобные этому, считаются окончательным решением, чтобы избежать повторного создания экземпляра, а также сбор мусора объектов, которые просто собираются быть повторно использован.

Для справки, вот что я использовал как очень общий Бассейн объекта: https://github.com/zeh/as3/blob/master/com/zehfernando/data/ObjectPool.as

Или более специализированную, что я использую в тех ситуациях, когда нужно кучу бросовым BitmapData экземпляров подобных размеров: https://github.com/zeh/as3/blob/master/com/zehfernando/data/BitmapDataPool.as

Я считаю, что внедрение класса VectorPool в формах того, что вам нужно, будет похоже на ссылку выше.

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

// Create a vector of 9 items, filled with `nulls` 
var myPoints:Vector.<Point> = new Vector.<Point>(9, true); 

Это делает его более быстрым, так как с течением времени у вас не будет микрораспределений. Вы должны установить элементы непосредственно, вместо того, чтобы использовать push():

myPoints[0] = new Point(0, 0); 

Но это на самом деле вынужденная преимущество, так как установка векторные элементы быстрее, чем push().

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