0
votes

I have an array of buttons and I attached event listeners like this.

arr[c].addEventListener(MouseEvent.MOUSE_UP, Proxy.go(this, click, Model.categoriesListXml.category_0[i].category_1[j].@category_id, Model.categoriesListXml.category_0[i].category_1[j].@name));

150 of these used 32MB of memory.

When I used the following memory dropped to 2MB.

var categoryId:String = Model.categoriesListXml.category_0[i].category_1[j].@category_id;
var name:String = Model.categoriesListXml.category_0[i].category_1[j].@name;
arr[c].addEventListener(MouseEvent.MOUSE_UP, Proxy.go(this, click, categoryId, name));

All I did was put the xml elements their own vars before using in the event listener.

Does anyone know why this is happening?

My guess is that the entire XML object gets included rather than just the elements I need.

1

1 Answers

4
votes

I think it works as the following.

Try. Flash is very lazy when it comes to disposing anything XML-related. So lazy, in fact, that it even has System.disposeXML(...) method because otherwise an XML object might not be garbage collected even if you consciously remove every single reference to it.

Catch. It is important to understand, that most XML operations result in XML or XMLList object, say

// XML source.
var X:XML = <root a="1" />;

// You might think it returns String, but no, it is just autocast to String.
var a:String = X.@a;

// If you don't specify data type, this returns XMLList object of length 1,
// with an XML member of type "attribute", name "a" (or maybe "@a"), and so on.
var A:* = X.@a;

So, without explicitly casting your attribute to String you pass 2 XMLList objects as the function arguments instead (or so it seems).

Finally. Just looking at Proxy.go(...) tells us that it creates a delegate (which is a type of closure), an unnamed unbound function with the stored arguments list. It should look similar to this:

public function go(target:Object, method:Function, ...rest:Array):Function
{
    return function():void
    {
        method.apply(target, rest);
    }
}

This works due to ECMA standard (probably works with JavaScript as well) that allows closures to access all their parent method data: local variables and method arguments.

So, you have it. Some unnamed function keeps (pretty much forever) somewhere in the player's memory a list of untyped arguments, which contains your XMLList objects (which are persistent and not easily disposed of). Then you create 150 such monstrosities this way. It's only natural that memory leaks in fountains and niagaras.