Haxe Map Memory Cleanup Issue

394 Views Asked by At

So I have been using Haxe for a while and it has occurred to me recently that I don't really get what happens on some other the non-flash targets as far as memory cleanup. I mean 'new'ing everything and dumping it by setting references to null gives me this feeling that there are memory leakages, but I can't seem to find the documentation I'm looking for.

Specifically I use dictionaries/maps a decent amount. Like this:

var items:Map<String, MyObject> = new Map();

items.set("someKey", new MyObject(args...));

// Later
items["someKey"].doSomething();
items["someKey"].setVal(2);
...

// When Finished
items.remove("someKey");

The last line there just dumps my object somewhere into oblivion and hopefully gets garbage collected (at least on the Flash target).

I put together a little program just to see the cleanup in action on Flash/Neko and then change it for other targets, but I am failing to even see the cleanup on the Flash Neko target. Here is the project code:

    package;

import openfl.display.Sprite;
import openfl.events.Event;
import haxe.ds.StringMap;

import openfl.events.KeyboardEvent;
import openfl.ui.Keyboard;

class Main extends Sprite 
{
    private var keypressID:Int;
    private var itemID:Int;
    private var dict:StringMap<Sprite>; // Using this since I read Map<String, T> just compiles to StringMap<T>.

    public function new() 
    {
        super();

        addEventListener(Event.ENTER_FRAME, init);
    }

    private function init(event:Dynamic):Void
    {
        removeEventListener(Event.ENTER_FRAME, init);
        // Entry point.

        keypressID = 0;
        itemID = 0;
        dict = new StringMap();

        stage.addEventListener(KeyboardEvent.KEY_UP, keyPress);
    }

    private function keyPress(event:Dynamic):Void
    {
        if (Std.is(event, KeyboardEvent) && cast(event, KeyboardEvent).keyCode == Keyboard.A)
        {
            trace('ID: $keypressID - Adding Item');
            keypressID += 1;

            for (i in 0...10000)
            {
                itemID += 1;
                dict.set('$itemID', new Sprite());
            }
        }
        else if (Std.is(event, KeyboardEvent) && cast(event, KeyboardEvent).keyCode == Keyboard.R)
        {
            trace('ID: $keypressID - Removing Items');
            keypressID += 1;

            removeItems();
        }

        // Force garbage collector to run.
        else if (Std.is(event, KeyboardEvent) && cast(event, KeyboardEvent).keyCode == Keyboard.C)
        {
            trace('ID: $keypressID > Starting GC');
            keypressID += 1;

            forceGarbageCollection();
        }
    }

    private function removeItems()
    {
        trace('ID: $keypressID > Remove All Item');

        for (val in dict.keys())
        {
            dict.remove(val);
        }

        dict = new StringMap();
    }

    private function forceGarbageCollection():Void
    {
        neko.vm.Gc.run(true);   // This does not work.
    }
}

I run this on Windows and under task manager, my neko process only grows and never shrinks. Its gets up to 500MB quick when hitting 'A'. I then 'R' to remove all references to the items, but they never get collected it seems even when I force the GC.

I also tried storing openfl.util.Timer objects with event listeners attached to them to do traces and they never seem to get collected either. They just keep tracing. Now I suspect that may be because of the event listener reference, but am sure I have seen that trick in other AS3 memory leak tracking code.

Am I missing something or doing something wrong?

Edit:

I have modified the above question to reflect this, but I was mistaken about Flash player. I did get the memory to be reclaimed when running in the Flash player using flash.system.System.gc(); It seems the problem may be specific to neko which my question still addressed.

0

There are 0 best solutions below