PDA

Просмотр полной версии : Утечка памяти


allex
30.05.2013, 15:34
Доброго времени суток уважаемые гуру.У меня такая проблема - создаю постоянно объекты,и сразу их удаляю.Со временем падает fps а память сильно растет.Хотелось бы услышать Ваши советы.В прикреплении пример.Если нажать ё(~) ,то будет виден fps и память.Вот сам код создания объектов и удаление их.



import components.*;
import flash.events.Event;
import flash.display.MovieClip;

var Component:Components=new Components(stage);

var arrOfElements:Array = [];

var i:int=0;
var j:int =0;
addEventListener(Event.ENTER_FRAME, stageEF);

function stageEF(e:Event){
for(i=0; i<3; i++){
var newmc:MovieClip =new mcAs();
newmc.x=stage.stageWidth/2;
newmc.y=300;
newmc.scaleX=newmc.scaleY=2*(0.5-Math.random());
newmc.scaleY=Math.abs(newmc.scaleY);
addChild(newmc);
arrOfElements.push(newmc);
}

for (j = 0; j< arrOfElements.length;j++ )
{
trace (arrOfElements.length)
if (arrOfElements[j] == arrOfElements[j].totalFrames)
removeChild(arrOfElements[j]);
arrOfElements[j] = null;
arrOfElements.splice(j,1);
}

}

Tails
30.05.2013, 16:14
Удаляющий отработанные объекты код написан не верно:
if (arrOfElements[j].currentFrame == arrOfElements[j].totalFrames){
removeChild(arrOfElements[j]);
arrOfElements[j] = null; // Не обязательно
arrOfElements.splice(j,1);
j--;
}

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

Зачем вам хранить спрайты в отдельном массиве? Их можно получать из дисплей контейнера, в котором они лежат.

Final Hope
30.05.2013, 17:51
Я где-то слышал, что лучше не создавать каждый раз новые объекты, а хранить старые в так называемом пуле (бассейне). Например, имеется пул. В этот пул сохраняется необходимое число объектов. А потом, когда нужно, из пула берутся объекты и добавляются на сцену. А когда на сцене объекты больше не нужны, то они обратно прячутся в пул. Тем самым память не трещит по швам. :) Если я ничего не путаю, то выглядит это примерно так:
import flash.display.Sprite;
import flash.events.Event;
import flash.text.TextField;

var particlesOnPool:Vector.<Sprite> = new <Sprite>[];
var particlesOnScene:Vector.<Sprite> = new <Sprite>[];
const COUNT_ON_TIME:int = 3;
const FLOOR:int = 300;

var traceTextField:TextField = new TextField();
traceTextField.width = 300;
this.addChild(traceTextField);

stage.addEventListener(Event.ENTER_FRAME, stage_enterFrameHandler);
//----------------------------------------------------------------
// Methods
//----------------------------------------------------------------
function addNewParticle():void
{
var particle:Sprite = new Sprite();
particle.graphics.beginFill(0x000000);
particle.graphics.drawCircle(0, 0, 2);
particlesOnPool.push(particle);
}
//----------------------------------------------------------------
// Event Handlers
//----------------------------------------------------------------
function stage_enterFrameHandler(event:Event):void
{
var particle:Sprite;
for (var i:int = 0; i < COUNT_ON_TIME; i++)
{
if (particlesOnPool.length != 0)
{
particle = particlesOnPool.pop();
particle.x = 200 + Math.random() * 50;
particle.y = 200 + Math.random() * 50;
this.addChild(particle);
particlesOnScene.push(particle);
}
else
{
addNewParticle();
i--;
}
}
var particlesOnSceneLength:int = particlesOnScene.length;
for (i = 0; i < particlesOnSceneLength; i++)
{
particle = particlesOnScene[i];
particle.y += 3;
if (particle.y >= FLOOR)
{
this.removeChild(particle);
particlesOnScene.splice(i, 1);
particlesOnPool.push(particle);
particlesOnSceneLength = particlesOnScene.length;
i--;
}
}
var particlesOnPoolLength:int = particlesOnPool.length;

traceTextField.text = "На сцене: " + particlesOnSceneLength.toString() +
" | В запасе: " + particlesOnPoolLength.toString() +
" | Всего партиклов в памяти: " + (particlesOnSceneLength + particlesOnPoolLength).toString();
}
Untitled-4.swf

allex
30.05.2013, 18:09
Удаляющий отработанные объекты код написан не верно:
if (arrOfElements[j].currentFrame == arrOfElements[j].totalFrames){
removeChild(arrOfElements[j]);
arrOfElements[j] = null; // Не обязательно
arrOfElements.splice(j,1);
j--;
}

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

Зачем вам хранить спрайты в отдельном массиве? Их можно получать из дисплей контейнера, в котором они лежат.


спасибо за ответ,как то с j-- не догадался. А вот почему обнулять не обязательно?И если происходит ремув объектов,разве можно брать из дисплея контейнера?

Tails
30.05.2013, 18:18
Если есть возможность, нужно делать с пулом, как посоветовали выше.

Обнулять не обязательно, потому-что вы следующей строкою и так удаляете этот итем из массива.
Если делать без массива и брать из дисплей контейнера, то к удалённым объектам обратиться разумеется будет нельзя. Но вы в вашем коде к ним и не обращаетесь.