Onelong

分享知识,与你一起进步......
RSS icon Home icon
  • flash player 9 垃圾收集器

    post by onelong / 2010-3-28 5:14 Sunday [业界]

    ActionScript3.0,引入AVM2之后,ActionScript3.0在执行速度上有了很大提高,所以使支持更复杂的组件成为可能。它引入了E4Xsocketsbyte 数组对象、新的显示列表模型、正则表达式、正式化的事件和错误模型以及其它特性,它是一个令人炫目的大杂烩。巨大的能力意味着巨大的责任,这对ActionScript3.0来说一点没错。引入这些新控件带来一个副作用:垃圾收集器不再支持自动为你收集垃圾等假设。也就是说Flash开发者转到ActionScript3.0之后需要对关于垃圾收集如何工作以及如何编程使其工作更加有效具备较深入的理解。没有这方面的知识,即使创建一个看起来很简单的游戏或应用程序也会出现SWF文件内存泄露、耗光所有系统资源(CPU/内存)导致系统挂起甚至机器重启。  要理解如何优化你的ActionScript3.0代码,你首先要理解垃圾收集器如何在FlashPlayer 9中工作。Flash有两种方法来查找非活动对象并移除它们。 
    关于垃圾收集器  垃圾收集器是一个后台进程它负责回收程序中不再使用的对象占用的内存。非活动对象就是不再有任何其他活动对象引用它。为便于理解这个概念,有一点非常重要,就是要意识到除了非原生类型(Boolean, String, Number, uint, int除外),你总是通过一个句柄访问对象,而非对象本身。当你删除一个变量其实就是删除一个引用,而非对象本身。  以下代码很容易说明这一点:   ActionScript代码

    1. // create a new object, and put a reference to it in a:  
    2. var a:Object = {foo:"bar"}  
    3. // copy the reference to the object into b:  
    4. var b:Object = a;  
    5. // delete the reference to the object in a:  
    6. delete(a);  
    7. // check to see that the object is still referenced by b:  
    8. trace(b.foo); // traces "bar", so the object still exists.  


    如果我改变上述示例代码将b也删除,它会使我创建的对象不再有活动引用并等待对垃圾收集器回收。ActionScript3.0 垃圾回收器使用两种方法定位无引用的对象 : 引用计数法和标识清除法。
     
    引用计数法  引用计数法是一种用于跟踪活动对象的较为简单的方法,它从ActionScript1.0开始使用。当你创建一个指向某个对象的引用,该对象的引用计数器加1;当你删除该对象的一个引用,该计数器减1。当某对象的计数器变成0,该对象将被标记以便垃圾回收器回收。  这是一个例子:   ActionScript代码

    1. var a:Object = {foo:"bar"}  
    2. // the object now has a reference count of 1 (a)  
    3. var b:Object = a;  
    4. // now it has a reference count of 2 (a & b)  
    5. delete(a);  
    6. // back to 1 (b)  
    7. delete(b);  
    8. // the reference count down is now 0  
    9. // the object can now be deallocated by the garbage collector  

      引用计数法简单,它不会非CPU带来巨大的负担;多数情况下它工作正常。不幸地是,采用引用计数法的垃圾回收器在遇到循环引用时效率不高。循环引用是指对象 交叉引用(直接、或通过其他对象间接实现)的情况。即使应用程序不再引用该对象,它的引用计数器仍然大于0,因此垃圾收集器永远无法收集它们。下面的代码 演示循环引用是怎么回事:   ActionScript代码
    1. var a:Object = {}  
    2. // create a second object, and reference the first object:  
    3. var b:Object = {foo:a};  
    4. // make the first object reference the second as well:  
    5. a.foo = b;  
    6. // delete both active application references:  
    7. delete(a);  
    8. delete(b);  

    上 述代码中,所有应用程序中活动的引用都被删除。我没有任何办法在程序中再访问这两个对象了,但这两个对象的引用计数器都是1,因为它们相互引用。循环引用 还可以更加负责 (a 引用 c, c引用b, b引用a, 等等) 并且难于用代码处理。FlashPlayer 6 7XML对象有很多循环引用问题: 每个 XML 节点被它的孩子和父亲引用,因此它们从不被回收。幸运的是FlashPlayer 8 增加了一个叫做标识-清除的新垃圾回收技术。  
    标识-清除法  ActionScript3.0 (以及FlashPlayer 8) 垃圾回收器采用第2种策略标识-清除法查找非活动对象。FlashPlayer从你的应用程序根对象开始(ActionScript3.0中简称为root)直到程序中的每一个引用,都为引用的对象做标记.接下来,FlashPlayer遍历所有标记过的对象。它将按照该特性递归整个对象树。并将从一个活动对象开始能到达的一切都标记。该过程结束后,FlashPlayer可以安全的假设:所有内存中没有被标记的对象不再有任何活动引用,因此可以被安全的删除。    
    FlashPlayer
    采用标记清除方法标记不再有活动引用的对象  标记-清除法非常准确。但是,由于FlashPlayer 遍历你的整个对象结构,该过程对CPU占用太多。FlashPlayer 9 通过调整迭代标识-清除缩减对CPU的占用。该过程跨越几个阶段不再是一次完成,变成偶尔运行。  
    延期(执行)垃圾回收器和不确定性  FlashPlayer 9垃圾回收器操作是延期的。这是一个要理解的非常重要的概念:当你的对象的所有引用删除后,它不会被立即删除。而是,它们将在未来一个不确定的时刻被删除(从开发者的角度来看)。垃圾收集器采用一系列启发式技巧诸如查看RAM分配和内存栈空间大小以及其他方法来决定何时运行。作为开发者,你必须接受这样的事实:不可能知道非活动对象何时被回收。你还必须知道非活动对象将继续存在直到垃圾收集器回收它们。所以你的代码会继续运行(enterFrame 事件会继续)、声音会继续播放、装载还会发生、其它事件还会触发等等。  
    记住,在FlashPlayer中你无权控制何时运行垃圾收集器去回收对象。作为开发者,你需要尽可能把你的游戏或应用程序中无用的对象应用清除。管理无用对象的策略将会在我的另一篇文章重点介绍:FlashPlayer 9的资源管理策略。  下图模拟垃圾回收器中总内存(包含活动对象和非活动对象的和,译者注)的锯齿状部分(点击图2或下方链接)。锯齿 的产生是由于垃圾回收器执行回收(原文执行 清除,疑为执行回收)。点击该图并注意,按下空格键来中止或重启,并在运行时按住up/down键头以控制内存使用趋势

    标签: flash avm2
    引用地址:
     

    我要评论