Actionscript 3 AS3内存管理逆向工程

Actionscript 3 AS3内存管理逆向工程,actionscript-3,flash,garbage-collection,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 -

有人知道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();
        }
    }
}
public类MemoryTesting扩展了Sprite
{
静态保护变量列表:Array=null;
公用函数onKeyDown(事件:KeyboardEvent):无效{
如果(event.keyCode==65){//A键-添加内存
if(list==null){
列表=[];
对于(var指数:int=0;指数<10000000;++指数){
list.push(新矩阵x3d());
}
}
}
否则{//任何其他键都会删除内存。
如果(列表){
变量大小:int=list.length;
对于(变量索引:int=0;索引
在Windows 7中运行Flash Player调试器单机版11.4r402。观察任务管理器,没有按下任何键,调试器在11000 K时处于空闲状态

按a键(添加10Mil Matrix3D类)将占用962000K的空间

按另一个键(删除对矩阵的引用并将数组置零)取决于我按它的次数

  • 我们第一次调用GC-下降到255000k
  • 第二个GC调用-92000 K
  • 第三名-52000 K
  • 福斯-42000 K
  • 第五-39000 K
  • 第六次和在38000 K下坐下后的任何连续时间
我听到人们谈论GC等待“适当时机”收集。但这是一个空的应用程序,甚至不是一个enter_frame事件,您没有时间让它空闲以删除剩余的27000k(38000-11000)

坐在新低,如果我们重新添加矩阵,我们将返回到975000 K

也就是说,比第一次多了13000 K。如果我重复这个添加/删除操作,它将保持不变,返回到975000 K和38000 K

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

我已经读过多次,即使手动调用GC也不好,更不用说6次了。但如果我不释放,Matrix3D就不会被释放

有人是怎么处理的?我在初始化结束时给GC打6次电话好吗

编辑:

我在release模式下测试差异,以及在没有System.gc()调用的情况下,如果它不能从flash中释放内存,是否至少可以正确地重新使用它。它最终会这样做,但有一个新的,更高的足迹。一个完整的列表位于990000 K,清除它需要1050000 K


这适用于最初需要962000 K RAM的数据。这是90MB奇怪的内部闪存GC内存。更不用说忽略它永远不会将内存返回给操作系统(没有显式的GC调用)

Actionscript的GC很奇怪,没什么可说的

如果您尝试使用类似的方法,它会很有帮助(我刚刚测试过,GC在第一次尝试(按键)时会清除内存),只是将数组更改为向量以更快地测试,同样的情况也应该发生在数组中。在这种情况下,我的环境是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)

        }
    }
}
以下是freat的文章:
这样的东西让我想回到C++。至少我们有控制权。应该始终可以选择关闭语言的GC并手动执行操作。出于价值考虑,Adobe福音派倾向于建议不要使用
System.GC()
。首先,它只能在某些情况下工作(请参阅live docs),其次,当需要更多内存时,Flash会释放内存。整个系统将自动运行,而不是手动运行;您应该将该索引第一个列表中的对象清空[i]=null;list.pop();,所以这可能是你的内存泄漏。可以为空的对象越多越好。此外,System.gc()只能在播放器的调试版本中调用,生产版本将忽略它。@Jono这意味着当您为普通用户发布SWF时,他们将始终看到1G的使用量。来自C++的你理解GC的重要性,但是AS3你试图改变那些不被程序员改变的东西。这种语言最初是为了设计者而编写的,尽管在较新的版本(as3)中,它更像是一种传统语言,但它仍然源于AS1。大多数人说AS3是一头猪,它占用了很多资源,但这确实很重要。您的示例限制了1G的ram,但并没有释放它。至少这是你被引导去相信的。仅仅因为GC没有,并不意味着1G是不可用的,它只是意味着flash正在保留它。当flash播放器感觉需要释放内存时,它会释放内存,这是因为你正确地标记了GCG的所有内容。当使用3 GCs时,它会使用参考计数、标记和扫描。标记和扫描速度很慢,这是您试图通过将对象设置为null并删除事件侦听器和对该对象的所有引用来避免的。玩家在正常情况下不会释放内存,因为分配内存是昂贵的,只有在有理由释放内存时才会这样做。调用System.gc()只是强制执行不需要执行的清理。我的总体观点是做好你的工作,正确地编程你的应用程序,播放器会完成它的工作,并在需要时清除内存。
try {
new LocalConnection().connect('foo');
new LocalConnection().connect('foo');
} catch (e:*) {}