AS3内存管理逆向工程

时间:2014-01-16 17:16:31

标签: actionscript-3 flash garbage-collection

有没有人想出AS3如何实际处理垃圾收集?在我正在开发的游戏中,我有很多问题释放内存。

做了一个小演示:

public class MemoryTesting extends Sprite
{
    static protected var list:Array = null;

    public function onKeyDown(event:KeyboardEvent):void {
        if( event.keyCode == 65 ){ //A key - adds memory
            if( list == null ){
                list = [];
                for( var index:int = 0; index < 10000000; ++index ){
                    list.push(new Matrix3D());
                }
            }
        }
        else{ //Any other key removes memory.
            if( list ){
                var size:int = list.length;
                for( var index:int = 0; index < size; ++index ){ 
                    list.pop();
                }
                list.length = 0;
                list = null;
            }
            System.gc();
        }
    }
}

在Windows 7中运行Flash Player调试器独立11.4r402。在没有按键的情况下观察任务管理器,调试器闲置在11,000 K.

按a(添加10Mil Matrix3D类)可将其提升至962,000 K.

按另一个键(删除对矩阵的引用并使数组无效)取决于我按下它的次数。

  • 我们第一次打电话给GC - 降至255,000 K.
  • 第二次GC呼叫 - 92,000 K.
  • 第三名 - 52,000 K.
  • Forth - 42,000 K.
  • 第五 - 39,000 K。
  • 第六&amp;在38,000 K之后的任何连续时间。

我听到有人在谈论GC等待收集的“适当时机”。但这是一个空的应用程序,甚至不是一个enter_frame事件,没有多少时间你可以让它空闲,以便删除剩余的27,000 K(38,000 - 11,000)。

坐在新的低点,如果我们重新添加矩阵,我们会回升到975,000 K.

也就是说,比第一次增加13,000 K.如果我重复这个添加/删除,它会保持不变,最高可达975,000 K,最低可达38,000 K.

请记住,此应用程序中没有任何内容。我的实际应用程序有650mb的原始位图数据,更不用说100mb的SWF解析和500mb的XML类,我只在初始化代码中使用。

我多次读过,即使手动调用GC也不好,更不用说6次了。但如果不这样做,Matrix3D都不会发布。

有人怎么办?我应该在初始化结束时调用GC 6次吗?

修改

我在发布模式下测试差异以及是否在没有System.gc()调用的情况下,如果它没有从闪存释放内存,至少重新使用它。它最终确实如此,但具有更高的占地面积。完整列表位于990,000 K,清除它需要1,050,000 K.

这适用于最初花费我们962,000 K RAM的数据。这是90MB奇怪的内部闪存GC内存。更别说忽略它不会将内存返回给操作系统(没有显式的GC调用)。

1 个答案:

答案 0 :(得分:1)

Actionscript的GC很奇怪,无话可说,

如果您尝试使用这样的东西,它会有所帮助(我刚刚测试过并且GC在第一次尝试时清除了内存(按键点击)),只需将Array更改为Vector以便更快地测试,就像这样也应该与Array一起发生。在这种情况下,我的环境是FlashCC。

package
{
import flash.display.Sprite;
import flash.events.KeyboardEvent;
import flash.geom.Matrix3D;
import flash.net.LocalConnection;
import flash.system.System;
import flash.utils.setTimeout;

public class MemoryTesting extends Sprite
{
    var list:Vector.<Matrix3D> = null;

    function MemoryTesting()
    {
        stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
    }

    public function onKeyDown(event:KeyboardEvent):void
    {

        var matrx:Matrix3D;
        var index:int
        if (event.keyCode == 13)
        { 
            trace(System.totalMemory, "starting to fill...")

            if (list == null)
            {
                list = new Vector.<Matrix3D>
                for (index = 0; index < 1000000; ++index)
                {
                    matrx = new Matrix3D();
                    list.push(matrx);
                }
            }
            trace(System.totalMemory, " done...")
        }
        else
        { 
            if (list)
            {
                trace(System.totalMemory, " preparing to delete...")


                list.splice(0, list.length);
                list = null;

            }

            //force GC to work normally, it really helps (at least in my case)
            try
            {
                new LocalConnection().connect('foo');
                new LocalConnection().connect('foo');
            }
            catch (e:*)
            {
            }

            setTimeout(function()
                {
                    trace(System.totalMemory, " deleted")
                }, 50)

        }
    }
}

}

这个奇怪的片段对大多数情况都有帮助

try {
new LocalConnection().connect('foo');
new LocalConnection().connect('foo');
} catch (e:*) {}

这是一篇有趣的文章: http://gskinner.com/blog/archives/2006/08/as3_resource_ma_2.html