Memory leak when loading SWF
I have a loader SWF that runs some code in the background and loads other SWFs. Using this code:
private function loadScreensaver():void {
screensaverSWF = new Loader();
var req:URLRequest;
switch(areaNumber){
case 1 :
req = new URLRequest("exNorthernFrontierScreensaver.swf");
break;
case 2 :
req = new URLRequest("exRomanEmpireScreensaver.swf");
break;
case 3 :
开发者_运维问答 req = new URLRequest("exRomanCarlisleScreensaver.swf");
break;
case 4 :
req = new URLRequest("exRomanBritainScreensaver.swf");
break;
}
screensaverSWF.load(req);
addChild(screensaverSWF);
GAME_STATE = SCREENSAVER;
}
I load the screensaver and add it to the stage. Using MonsterDebugger I can see that memory steadily rises from around 80mb upwards until the application exits (Im using windows projector). What I can't work out is why, there is no code attached to the screensaver SWF, just some timeline animations of things fading in and out. Any idea what's going on here?
EDIT: I've kept testing and found where I have an image that starts of stage then tweens on and off and is removed. When it loops it adds to memory again, as if the first image is still kept. This is all done on the timeline.
EDIT2: http://www.rezmason.net/blog/caching-timeline-objects-in-flash This appears to be the problem but doesn't give a solution. This screensaver could run up to 6 hours a day, at the moment it exits after 2.
You're never going to clear externally loaded swfs out of memory. Once you load something from outside, it'll be a miracle if you see the memory drop afterwards. Therefore, if you're ever going to find a situation where you might possibly "load" the same asset more than one time during the life of the swf you need instead to hold onto the originally loaded asset and just re-use it. That function looks like it might be called repeatedly, and you're just re-loading already loaded assets every time you do that.
That way the worst that will happen is you'll just have each of the screen savers hanging around but only just one of each.
OK sorted the problem. It appears removing images towards the end of an animation and then looping the animation causes them to be added to memory repeatedly. Images are now either made invisible or moved off stage towards the end so they are reused.
While you cannot ever unload the code and any embedded images from the remote SWF from memory, you can usually dispose a lot of data that was created. One simple way is to iterate over every display child in the swf and call removeChild
on each of them. For good measure, I also call stop()
on every child that is of type Movieclip
. This will help lower the memory footprint from images/animations that where instanced for use in its display.
I'm not sure if this will fix it, but whenever new code is loaded it is loaded into the current ApplicationDomain, and you can't unload just "some" code from an application domain. Maybe if you create a new ApplicationDomain for each swf you load, it might get garbage collected once you de-reference it.
screensaverSWF.load(req, new LoaderContext(false, new ApplicationDomain()));
If you run into this problem again, the Object tab of SWFWire Debugger might help you find the memory leak by showing a list of objects that have been added or removed (assuming everything is AS3).
精彩评论