それで、私はしばらくHaxeを使用してきましたが、最近、メモリのクリーンアップに関して、フラッシュ以外のターゲットで何が起こっているのかがよくわからないことに気づきました。つまり、すべてを「新規」にし、参照を null に設定してダンプすると、メモリ リークがあるように感じますが、探しているドキュメントが見つからないようです。
具体的には、辞書/地図をかなりの量使用しています。このような:
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");
そこの最後の行は、オブジェクトを忘却のどこかにダンプし、できればガベージコレクションを取得します (少なくとも Flash ターゲットでは)。
Flash/Neko でのクリーンアップの動作を確認するためだけに小さなプログラムを作成し、それを他のターゲットに変更しましたが、Flash Neko ターゲットでのクリーンアップを確認することさえできません。プロジェクトコードは次のとおりです。
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.
}
}
これを Windows で実行し、タスク マネージャーの下で実行すると、neko プロセスは拡大するだけで、縮小することはありません。「A」を押すと、最大 500MB 速くなります。次に、「R」を使用してアイテムへのすべての参照を削除しますが、GC を強制しても収集されないようです。
また、openfl.util.Timer オブジェクトにイベント リスナーをアタッチしてトレースを実行しようとしましたが、それらも収集されないようです。彼らはただ追跡し続けます。これはイベント リスナーの参照が原因ではないかと考えていますが、他の AS3 メモリ リーク追跡コードでそのトリックを見たことは確かです。
私は何かを見逃していますか、何か間違っていますか?
編集:
これを反映するために上記の質問を修正しましたが、Flash Player について誤解していました。flash.system.System.gc(); を使用して Flash プレーヤーで実行すると、メモリが再利用されました。問題は、私の質問がまだ対処している neko に固有のもののようです。