dcsimg
A Flash Developer Resource Site

Results 1 to 13 of 13

Thread: Memory Leakage?

  1. #1
    Member
    Join Date
    May 2009
    Posts
    62

    Memory Leakage?

    I have the following class.
    Code:
    public class TestObject extends Sprite
    {
    	private var bitmap:Bitmap;	
    	private var realWidth:Number = 550;
    	
    	private var color:HSLColor = new HSLColor(200, 50, 100);
    	
    	private var amp:Number = 0;
    	private var ampAcc:Number = 1;
    	
        public function TestObject()
    	{
    		bitmap = new Bitmap(null, "auto", true);
    		bitmap.bitmapData = new BitmapData(550, 400, true, 0x00000000);
    
    		addEventListener(Event.ENTER_FRAME, update);
        }
    	
    	private function drawBand(base:Number, amplitude:Number, wavelength:Number, offset:Number, color:uint, dir:Boolean)
    	{			
    		offset = offset % wavelength;
    		var xIntercept:Number;
    		
    		graphics.beginFill(color);
    			
    		if (dir)
    		{
    			xIntercept = -offset;
    			graphics.moveTo(xIntercept, 0);
    			graphics.lineTo(xIntercept, base);
    			
    			while (xIntercept <= realWidth)
    			{
    				graphics.curveTo(xIntercept + wavelength / 2, base + amplitude, (xIntercept = xIntercept + wavelength), base);
    				amplitude *= -1;
    			}
    			
    			graphics.lineTo(realWidth, 0);
    		}
    		else
    		{
    			xIntercept = realWidth + offset;
    			graphics.moveTo(xIntercept, 0);
    			graphics.lineTo(xIntercept, base);
    			
    			while (xIntercept >= 0)
    			{
    				graphics.curveTo(xIntercept - wavelength / 2, base + amplitude, (xIntercept = xIntercept - wavelength), base);
    				amplitude *= -1;
    			}
    			
    			graphics.lineTo(0, 1);
    		}
    	}
    	
    	private function update(evt:Event)
    	{
    		var color2:HSLColor;
    		color.h += 1;
    		
    		if (amp > 100 || amp < -100)
    		{
    			ampAcc *= -1;
    		}
    		amp += ampAcc;
    		
    		graphics.clear();
    		
    		for (var i = 0; i < 10; i++)
    		{
    			color2 = new HSLColor(color.r, color.g, color.b);
    			color2.h += i * 360/10;
    			drawBand(500 / 10 * (10 - i), amp, 100, i * 50, color2.color, i % 2 == 1);
    		}
    		
    		bitmap.bitmapData.draw(this);
    		
    		graphics.clear();
    		graphics.beginBitmapFill(bitmap.bitmapData);
           	graphics.drawCircle(200, 200, 200);
    	}
    }
    When about 10 or so are on screen the FPS drops to rougly 80. Once they bounce offscreen and are removed, the FPS remains at 80 (it should return to 120). I have confirmed that the object was deleted, so what else could cause the FPS to remain low after deconstruction?

  2. #2
    ___________________
    Join Date
    May 2004
    Posts
    3,174
    removing it from the display list won't get rid of that enterFrame listener. you can add a listener for the "removed" event that can then get rid of the enterframe (and the remove listener while you're at it).

  3. #3
    http://pat.theorigin.net cresquin's Avatar
    Join Date
    Jun 2003
    Location
    Los Angeles, CA
    Posts
    685
    when an object still has a listener referenced to it, the object will not be garbage collected.

    You have two options:
    1. as stated above wait until the object is no longer on stage and remove the ENTER_FRAME listener.

    2. simply setup the listener with weak referencing. (it is set up as strongly referenced by default.

    PHP Code:
    addEventListener(Event.ENTER_FRAMEupdatefalse0true); 

  4. #4
    Member
    Join Date
    May 2009
    Posts
    62
    Ah.... thanks.

    That makes sense.

  5. #5
    Senior Member
    Join Date
    May 2004
    Posts
    226
    In CS3 the useWeakReference argument does not work with the ENTER_FRAME event or is at best inconsistent, something excludes it from gc. I'm not sure if its a bug or there is some logical reason but I would call it a bug. Things might be different in CS4 but I doubt it since the same runtime player is used.

    Best to define a destroy method and attach it to the REMOVED_FROM_STAGE event then manually clear all your listeners.

  6. #6
    Senior Member joshstrike's Avatar
    Join Date
    Jan 2001
    Location
    Alhama de Granada, España
    Posts
    1,131
    v5000 is right...
    objects with weak-referenced ENTER_FRAME listeners can NOT be relied on to have their listeners removed when they are taken out of the display chain...I'm not sure why this is so, but a destruction function that removes the listener is critical in these cases...

  7. #7
    Senior Member Alluvian's Avatar
    Join Date
    Jun 2006
    Posts
    967
    Is there a snippet of code that can reliably tag a MovieClip for garbage collection?

    I state movieclip because elsewhere I have seen reports of rogue timeline operations causing movieclips (even with just 1 frame) from getting collected. The solution there was to make a deconstructor that added a stop() to the clilp.

    If that type of snippet is not around, is there an easy way to get rid of all listener events on an object? I can see if they are being dynamically added you might not know how many or what listeners are on an object...

    Final question. Are there other listeners besides ENTER_FRAME that are unreliable with weak references? If that is the only one, then I guess you can just weak reference everything and then explicitly destroy the enterframe.

    I lied, one more! Isn't it true that any variables defined to reference the object will also keep it from being collected?

  8. #8
    Senior Member joshstrike's Avatar
    Join Date
    Jan 2001
    Location
    Alhama de Granada, España
    Posts
    1,131
    I don't use MovieClips very often, and I haven't experienced the need to stop() them to keep them from being garbage collected; although it wouldn't surprise me.

    There's no automatic way to remove all your listeners for an object, but I always weak reference all listeners: There is never a reason NOT to weak reference a listener. But as to why it appears to work in some cases and not others, this is what I believe is happening, and someone can correct me if I'm wrong about it:

    Weak referencing basically makes it so that if Class A listens to Class B for a click, and B disappears from the display chain, A's listener will not keep that instance of B from being marked for garbage collection solely by virtue of having a reference to it. On the other hand, if B had a weak listener on A, when B was removed from the chain, that listener may still be keeping B alive, because it is listening for something that still belongs to the chain. In other words, I'm pretty sure the weak reference part comes into play by killing the listener when its target is removed; but not when the target is still there and the object doing the listening is removed. Does that make sense?

    And as far as variables keeping something alive by reference, as long as they are scoped within a function, they will not keep it alive. But if they are properties of a class, then yes, they will keep those references alive as long as they themselves are alive. You have to dereference them by setting them null or, in the case of properties of dynamic objects, by deleting their reference from the object.

    Hope that helps...

    Oh and one more thing, always check your memory in a browser. The IDE player does not garbage collect normally the way the plugin player does, and can give misleading results.

  9. #9
    Senior Member Alluvian's Avatar
    Join Date
    Jun 2006
    Posts
    967
    Good tips!

    and...


    Weak referencing basically makes it so that if Class A listens to Class B for a click, and B disappears from the display chain, A's listener will not keep that instance of B from being marked for garbage collection solely by virtue of having a reference to it. On the other hand, if B had a weak listener on A, when B was removed from the chain, that listener may still be keeping B alive, because it is listening for something that still belongs to the chain. In other words, I'm pretty sure the weak reference part comes into play by killing the listener when its target is removed; but not when the target is still there and the object doing the listening is removed. Does that make sense?
    Not even a little, lol. Could you give examples of what A and B would be with some code?

  10. #10
    Senior Member joshstrike's Avatar
    Join Date
    Jan 2001
    Location
    Alhama de Granada, España
    Posts
    1,131
    Okay, here's what I mean... and again, I might not be right, but this is what it seems like to me:

    Code:
    package {
    	import flash.display.Sprite;
    	import flash.events.Event;
    	import flash.events.MouseEvent;
    	public class Alpha extends Sprite {
    		public var beta:Beta = new Beta();
    		public function Alpha():void {
    			addChild(beta);
    			beta.addEventListener(MouseEvent.CLICK,removeBeta,false,0,true);
    			beta.addEventListener(Event.ENTER_FRAME,doSomething,false,0,true);
    		}
    		private function doSomething(evt:Event):void {
    		}
    		private function removeB(evt:MouseEvent):void {
    			removeChild(beta); 
    			//If the CLICK listener was strong referenced, beta would not be garbage collected until 
    			//the listener was removed, even though beta is no longer on the display chain.
    			//However, since it was a weak listener, beta will now be garbage collected.
    			
    			//In this case, the ENTER_FRAME listener is on beta, and when beta is removed from the chain, 
    			//the ENTER_FRAME weak reference does not keep beta from being collected.
    		}
    	}
    }
    
    package {
    	import flash.display.Sprite;
    	import flash.events.Event;
    	import flash.events.MouseEvent;
    	public class Delta extends Sprite {
    		public function Delta(beta:Beta):void {
    			this.addEventListener(Event.ENTER_FRAME,doSomething,false,0,true);
    			//this listener will not keep Delta from being swept if it is removed from the display chain, 
    			//because the listener's target is Delta itself, and Delta's not there anymore.
    
    			beta.addEventListener(Event.ENTER_FRAME,doSomething,false,0,true);
    			//this listener WILL keep THIS CLASS (Delta) from being swept, EVEN THOUGH IT'S WEAK REFERENCED, because 
    			//its target, beta, has not been removed from the display chain. 
    			//if beta were removed however, then both beta and delta could be swept.
    		}
    		private function doSomething(evt:Event):void {
    		}
    	}
    }
    Anyone else's input on this would be good, too.
    Last edited by joshstrike; 06-02-2009 at 06:15 PM.

  11. #11
    Senior Member Alluvian's Avatar
    Join Date
    Jun 2006
    Posts
    967
    I think you are wrong in your Alpha.removeB method comments. beta is still a public property of alpha. I think you would have to removeChild(beta) AND set beta to null, or delete the instance of Alpha that beta is a property of... right?

  12. #12
    Senior Member joshstrike's Avatar
    Join Date
    Jan 2001
    Location
    Alhama de Granada, España
    Posts
    1,131
    Right. Right. My mistake.
    After you remove beta you'd have to set it to null in Alpha, before it could be swept. (Or remove Alpha from its parent and set it to null... that would also be sufficient.)
    I've been doing this by feel for a long time without ever formally writing this stuff out, so it's weird for me to look at it this way.

  13. #13
    Senior Member joshstrike's Avatar
    Join Date
    Jan 2001
    Location
    Alhama de Granada, España
    Posts
    1,131
    I guess the way I think of it is, the weak referenced listener lets the target be released if it's removed from the display chain; that and only that. Adding a weak listener to a permanent item like the stage, with a reference to a function in an item you want to destroy, doesn't do you any good because that listener would not be automatically dereferenced until its target (stage) was removed, or you removed it manually. And because it has to call a function in the class that placed it, the class that placed it can't be removed until it is.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  




Click Here to Expand Forum to Full Width

HTML5 Development Center