views:

2541

answers:

8

Does anyone know how to forcefully unload a ByteArray from memory in AS3?

I have tried (without success):


byteArray.length = 0;
byteArray = new ByteArray();

and

for ( var i:int=0; i<byteArray.length; i++ ) {
byteArray[i] = null;
}

Any ideas?

+1  A: 

Have a look at this article

http://www.gskinner.com/blog/archives/2006/06/as3_resource_ma.html

IANA actionscript programmer, however the feeling I'm getting is that, because the garbage collector might not run when you want it to.

Hence http://www.craftymind.com/2008/04/09/kick-starting-the-garbage-collector-in-actionscript-3-with-air/

So I'd recommend trying out their collection code and see if it helps

private var gcCount:int;
private function startGCCycle():void{
gcCount = 0;
addEventListener(Event.ENTER_FRAME, doGC);
}
private function doGC(evt:Event):void{
flash.system.System.gc();
if(++gcCount > 1){
removeEventListener(Event.ENTER_FRAME, doGC);
setTimeout(lastGC, 40);
}
}
private function lastGC():void{
flash.system.System.gc();
}
Jax
+2  A: 

(I'm not positive about this, but...)

AS3 uses a non-deterministic garbage collection. Which means that unreferenced memory will be freed up whenever the runtime feels like it (typically not unless there's a reason to run, since it's an expensive operation to execute). This is the same approach used by most modern garbage collected languages (like C# and Java as well).

Assuming there are no other references to the memory pointed to by byteArray or the items within the array itself, the memory will be freed at some point after you exit the scope where byteArray is declared.

You can force a garbage collection, though you really shouldn't. If you do, do it only for testing...if you do it in production, you'll hurt performance much more than help me.

To force a GC, try (yes, twice): flash.system.System.gc(); flash.system.System.gc();

You can read more at: http://www.craftymind.com/2008/04/09/kick-starting-the-garbage-collector-in-actionscript-3-with-air/

Karl Seguin
A: 

Unfortunately when it comes to memory management in Flash/actionscript there isn't a whole lot you can do. ActionScript was designed to be easy to use (so they didn't want people to have to worry about memory management)

The following is a workaround, instead of creating a ByteArray variable try this.

var byteObject:Object = new Object();

byteObject.byteArray = new ByteArray();

...

//Then when you are finished delete the variable from byteObject
delete byteObject.byteArray;

Where byteArray is a dynamic property of byteObject, you can free the memory that was allocated for it.

Redbaron
A: 

Thanks all., but still no luck.

I have tried combinations of all the suggestions and still no luck.

Here is some more info on what I am trying to accomplish. I am writing a MySQL driver for AS3 (http://assql.googlecode.com) and I am just trying to work out some memory issues.

Currently all data that is received from MySQL I am storing in a single Buffer (class that extends ByteArray). Then anywhere I need to read data from that Buffer I have a class (ProxiedByteArray) that simply points to that ByteArray and specifies the offset to start reading data from.

I have read countless articles on AS3 garbage collection, dynamic properties and using the delete keyword. However, none of which have helped me.

So, if I load say 20MB from MySQL, in the Task Manager the RAM for the application goes up by about 25MB. Then when I close the connection and try to dispose the ByteArray, the RAM never frees up. However, if I use System.totalMemory, flash player shows that the memory is being released, which is not the case.

Is the flash player doing something like Java and reserving heap space and not releasing it until the app quits?

+1  A: 

I believe you have answered your own question...

System.totalMemory gives you the total amount of memory being "used", not allocated. It is accurate that your application may only be using 20mb, but it has 5mb that is free for future allocations.

I'm not sure if the Adobe docs would shed light on the way that it manages memory...

Redbaron
+3  A: 

I don't think you have anything to worry about. If System.totalMemory goes down you can relax. It may very well be the OS that doesn't reclaim the newly freed memory (in anticipation of the next time Flash Player will ask for more memory). Try doing something else that is very memory intensive and I'm sure that you'll notice that the memory allocated to Flash Player will decrease and be used for the other process instead.

As I've understood it, memory management in modern OS's isn't intuitive from the perspective of looking at the amounts allocated to each process, or even the total amount allocated. When I've used my Mac for 5 minutes 95% of my 3 GB RAM is used, and it will stay that way, it never goes down. That's just the way the OS handles memory. As long as it's not needed elsewhere even processes that have quit still have memory assigned to them (this can make them launch quicker the next time, for example).

Theo
A: 

So, if I load say 20MB from MySQL, in the Task Manager the RAM for the application goes up by about 25MB. Then when I close the connection and try to dispose the ByteArray, the RAM never frees up. However, if I use System.totalMemory, flash player shows that the memory is being released, which is not the case.

Is the flash player doing something like Java and reserving heap space and not releasing it until the app quits?

Well yes and no, as you might have read from countless blogposts the GC in AVM2 is optimistic and will work it's own misterious ways. So it does work a bit like Java and tries to reserve heap space, however if you let it long enough and start doing other operations that are consuming some significant memory it will free that previous space. You can see this using the profiler over night with some tests running on top of your app.

Hth Pedro.

Pedro
A: 

So, if I load say 20MB from MySQL, in the Task Manager the RAM for the application goes up by about 25MB. Then when I close the connection and try to dispose the ByteArray, the RAM never frees up. However, if I use System.totalMemory, flash player shows that the memory is being released, which is not the case.

The player is "releasing" the memory. If you minimize the window and restore it you should see that the memeory is now much closer to what System.totalMemory shows.

You might also be interested in using FlexBuilder's profiling tools which can show you if you really have memory leaks.