`

flex garbage collection

    博客分类:
  • flex
阅读更多

I've been playing around with ActionScript 3.0 for a while now, and I'm really excited by its capabilities. The raw execution speed by itself provides so many possibilities. Toss in E4X, sockets, byte arrays, the new display list model, RegEx methods, a formalized event and error model, and a few dozen other features for flavor, and you have a pretty heady brew.

With great power comes great responsibility, and this is very true for ActionScript 3.0. A side effect of all this new control is that the garbage collector is no longer able to make as many assumptions about what it should automatically tidy up for you. This means that Flash developers moving to ActionScript 3.0 will need to develop a very strong understanding of how the garbage collector operates, and how to work with it effectively. Building even seemingly simple games or applications without this knowledge could result in SWFs that leak like a sieve, hogging all of a system's resources (CPU/RAM) and causing the user's system to hang—potentially even forcing them to hard reboot their computer.

To understand how to optimize your code for ActionScript 3.0, you'll first need an understanding of how the garbage collector works in Flash Player 9. Flash has two processes for finding objects that are not in active use and removing them. This article looks at both techniques and describes how they are relevant to your code.

At the end of this article you can find a simulation of the garbage collector in Flash Player 9 that visually demonstrates the concepts explained herein.

ABOUT THE GARBAGE COLLECTOR

The garbage collector is a behind-the-scenes process that is responsible for deallocating the memory used by objects that are no longer in use by the application. An inactive object is one that no longer has any references to it from other active objects. In order to understand this, it is very important to realize that when working with non-primitive types (anything other than Boolean, String, Number, uint, int), you are always passing around a reference to the object, not the object itself. When you delete a variable you remove the reference, not the object itself.

This is easily demonstrated in the code below:

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

If I were to update the code in the example above and delete "b" as well, it would leave my object with no active references and free it for garbage collection. The ActionScript 3.0 garbage collector uses two methods for locating objects with no active references: reference counting and mark sweeping.

REFERENCE COUNTING

Reference counting is one of the simplest methods for keeping track of active objects, and has been used in Flash since ActionScript 1.0. When you create a reference to an object, its reference count is incremented. When you delete a reference, its reference count is decremented. If the reference count of an object reaches zero, it is marked for deletion by the garbage collector.

Here's an example:

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

Reference counting is simple, it doesn't carry a huge CPU overhead, and it works well in most situations. Unfortunately, the reference counting method for garbage collection is not optimal when it comes to circular referencing. Circular referencing is the situation when objects cross-reference each other (directly, or indirectly via other objects). Even if the application is no longer actively using the objects, their reference counts remain above zero, so the garbage collector never removes them. The code below illustrates how this works:

var a:Object = {}
// create a second object, and reference the first object:
var b:Object = {foo:a};
// make the first object reference the second as well:
a.foo = b;
// delete both active application references:
delete(a);
delete(b);

In the code shown above, both of the active application references have been deleted. I no longer have any way of accessing the two objects from my application, but the reference counts of both objects are 1 because they reference each other. This situation can become much more complex (a   references  c , which references  b , which references  a , etc.) and can be difficult to deal with in code. Flash Player 6 and 7 had issues relating to circular referencing in XML objects: each XML node referenced both its children and its parent, so they were never deallocated. Fortunately, Flash Player 8  added a new garbage collection technique   called mark and sweep.

MARK SWEEPING

The second strategy employed by the ActionScript 3.0 (and Flash Player 8) garbage collector to find inactive objects is a method called mark and sweep. Flash Player starts at the root object of your application (which is conveniently called the "root" in ActionScript 3.0) and walks through every reference in it, marking each object it finds.

Next, Flash Player iterates through each of the marked objects. It continues this behavior recursively until it has traversed the entire object tree of your application, marking everything it can reach through an active reference. At the end of this process, Flash Player can safely assume that any objects in memory that are not marked no longer have any active references to them and can be safely deallocated. Figure 1 illustrates how this works: The green references were followed by Flash Player during marking, the green objects are marked, and the white objects will be deallocated.

Figure 1.   Objects that no longer have active references are identified by Flash Player using the mark and sweep method

Mark and sweep is very accurate. However, because Flash Player has to traverse your entire object structure, the process is costly in terms of CPU usage. Flash Player 9 reduces this cost by carrying out iterative mark and sweep—the process occurs over a number of frames, instead of all at once—and by running this process only occasionally.

DEFERRED GARBAGE COLLECTOR AND INDETERMINACY

In Flash Player 9, the garbage collector's operations are deferred. This is a very important thing to understand. Your objects will not be removed immediately when all active references are deleted. Rather, they will be removed at some indeterminate time in the future (from a developer standpoint). The garbage collector uses a set of heuristics that look at the RAM allocation and the size of the memory stack, among other things, to determine when to run. As a developer, you must accept the fact that you will have no way of knowing when, or even if, your inactive objects will get deallocated. You must also be aware that inactive objects will continue to execute indefinitely, until the garbage collector deallocates them, so your code will keep running (enterFrame events will continue), sounds will keep playing, loads will keep happening, other events will keep firing, and so on.

It's very important to remember that you have no control over when the garbage collector in Flash Player will deallocate your objects. As a developer, you will want to make the objects in your games and applications as inert as possible when you are finished with them. Strategies to manage this process will be the focus of my companion article,  Resource management strategies in Flash Player 9 .

Notice the sawtooth pattern of the total memory in the following garbage collection simulation (click Figure 2 or the link below it). The dips are caused when the collector carries out a sweep. Click on the chart to focus it, then press Spacebar to pause or restart, and hold the up/down arrows to change the memory usage trend as it runs.

Garbage collection simulation

Figure 2.   Garbage collection simulation

As shown in the following simulation (click Figure 3 or the link below it), drag out objects (round rectangles) and references to those objects. Then run reference counts or mark and sweep to see which objects would be collected. The number in an object indicates the number of references to that object.

Garbage collection simulation: mark and sweep

Figure 3.   Garbage collection simulation: mark and sweep

WHERE TO GO FROM HERE

Understanding garbage collection is going to be one of the most important steps for writing optimized code that ensures that your Flash project runs with minimal impact on the user's computer. Read my companion article,  Resource management strategies in Flash Player 9 , and visit the  Flash Developer Center   and  Flash Player Developer Center .

Also check out my blog at  gskinner.com   to read more about weak references and download helper classes that I've written.

ABOUT THE AUTHOR

Grant Skinner is the CEO and chief architect of  gskinner.com , a creative technology company with a focus on the Flash platform. He works with leading new media agencies and progressive corporate clients to create cutting-edge applications, campaigns, and multimedia pieces. His expertise in fusing coding with interface design, usability, marketing, and business logic has garnered international acclaim and resulted in a number of prestigious industry awards. Grant maintains an active blog at  gskinner.com/blog/   and an exhibit of his experimental work atincomplet.org . Read more about Grant in the  Flash: Ten years, ten perspectives   series.

http://www.adobe.com/devnet/flashplayer/articles/garbage_collection.html

翻译:理解FlashPlayer 9垃圾回收机制,欢迎指正
目前我暂时在研究ActionScript3.0,它的能力让我很激动。它的原生执行速度带来诸多可能(此句原文The raw execution speed by itself provides so many possibilities. raw本意未加工,原始的,这里的意思是指引入AVM2之后,ActionScript3.0在执行速度上有了很大提高,所以使支持更复杂的组件成为可能,译者注)。它引入了E4X、sockets、byte 数组对象、新的显示列表模型、正则表达式、正式化的事件和错误模型以及其它特性,它是一个令人炫目的大杂烩。  巨大的能力意味着巨大的责任,这对ActionScript3.0来说一点没错。引入这些新控件带来一个副作用:垃圾收集器不再支持自动为你收集垃圾等假设。也就是说Flash开发者转到ActionScript3.0之后需要对关于垃圾收集如何工作以及如何编程使其工作更加有效具备较深入的理解。没有这方面的知识,即使创建一个看起来很简单的游戏或应用程序也会出现SWF文件内存泄露、耗光所有系统资源(CPU/内存)导致系统挂起甚至机器重启。  要理解如何优化你的ActionScript3.0代码,你首先要理解垃圾收集器如何在FlashPlayer 9中工作。Flash有两种方法来查找非活动对象并移除它们。本文解释这两种技术并描述它们如何影响你的代码。  本文结尾你会找到一个运行在FlashPlayer9中的垃圾收集器模拟程序,它生动演示了这里解释过的概念。  

关于垃圾收集器    垃圾收集器是一个后台进程它负责回收程序中不再使用的对象占用的内存。非活动对象就是不再有任何其他活动对象引用 它。为便于理解这个概念,有一点非常重要,就是要意识到除了非原生类型(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 和 7的XML对象有很多循环引用问题: 每个 XML 节点被它的孩子和父亲引用,因此它们从不被回收。幸运的是FlashPlayer 8 增加了一个叫做标识-清除的新垃圾回收技术。   

标识-清除法    ActionScript3.0 (以及FlashPlayer 8) 垃圾回收器采用第2种策略标识-清除法 查找非活动对象。FlashPlayer从你的应用程序根对象开始(ActionScript3.0中简称为root)直到程序中的每一个引用,都为引用的对象做标记。  接下来,FlashPlayer遍历所有标记过的对象。它将按照该特性递归整个对象树。并将从一个活动对象开始能到达的一切都标记。该过程结束后,FlashPlayer可以安全的假设:所有内存中没有被标记的对象不再有任何活动引用,因此可以被安全的删除。图1 演示了它如何工作:绿色引用(箭头)曾被FlashPlayer 标记过程中经过,绿色对象被标记过,白色对象将被回收。     

Figure 1. FlashPlayer采用标记清除方法标记不再有活动引用的对象  标记-清除法非常准确。但是,由于FlashPlayer 遍历你的整个对象结构,该过程对CPU占用太多。FlashPlayer 9 通过调整迭代标识-清除缩减对CPU的占用。该过程跨越几个阶段不再是一次完成,变成偶尔运行。  延期(执行)垃圾回收器和不确定性    FlashPlayer 9垃圾回收器操作是延期的。这是一个要理解的非常重要的概念:当你的对象的所有引用删除后,它不会被立即删除。而是,它们将在未来一个不确定的时刻被 删除(从开发者的角度来看)。垃圾收集器采用一系列启发式技巧诸如查看RAM分配和内存栈空间大小以及其他方法来决定何时运行。作为开发者,你必须接受这 样的事实:不可能知道非活动对象何时被回收。你还必须知道非活动对象将继续存在直到垃圾收集器回收它们。所以你的代码会继续运行(enterFrame 事件会继续)、声音会继续播放、装载还会发生、其它事件还会触发等等。  记住,在FlashPlayer中你无权控制何时运行垃圾收集器去回收对象。作为开发者,你需要尽可能把你的游戏或应用程序中无用的对象应用清除。管理无用对象的策略将会在我的另一篇文章重点介绍:FlashPlayer 9的资源管理策略。  下图模拟垃圾回收器中总内存(包含活动对象和非活动对象的和,译者注)的锯齿状部分(点击图2或下方链接)。锯齿 的产生是由于垃圾回收器执行回收(原文执行 清除,疑为执行回收)。点击该图并注意,按下空格键来中止或重启,并在运行时按住up/down键头以控制内存使用趋势。  http://www.adobe.com/devnet/flashplayer/articles/garbage_collection.html#    

Figure 2. Garbage collection simulation  Garbage collection simulation    正如下面演示的一样(单击图3或下方链接),拖动对象(圆角矩形)到桌面并建立它们之间的引用(使用连线,译者注)。点击run reference或mark and sweep按钮以查看哪些对象会被回收。对象上有标识到该对象的引用个数。  http://www.adobe.com/devnet/flashplayer/articles/garbage_collection.html#    

Figure 3. Garbage collection simulation: mark and sweep  Garbage collection simulation: mark and sweep    从这里通往何方?    理解垃圾回收机制是编写优化代码的重要前提。优化的代码保证你的Flash项目在客户机器上运行时不会带来大的冲击。阅读更多相关文章,FlashPlayer 9中的资源管理策略,或访问Flash开发者中心以及FlashPlayer开发者中心。  也可以查看我的blog gskinner.com 阅读关于弱引用的文章并下载我写的一个辅助类。  

关于作者    Grant Skinner是gskinner.com公司CEO及架构师,该公司是一个Flash开 发和咨询公司。他与新媒体机构以及有进取心的客户合作开发前沿应用、游戏和多媒体程序。他擅于将支持接口设计的代码、可用性、市场和业务逻辑融汇,由此带 给他国际上赞誉并获得包括Best Canadian Developer at FITC 2005在内的多个业界大奖。Grant在gskinner.com/blog/写blog并在incomplet.org展示他的验证性的创作。

http://bbs.airia.cn/ActionScript/thread-3656-1-1.aspx

分享到:
评论
1 楼 luhantu 2012-07-06  
辛苦你了,写的很不错,翻译的也很不错。

相关推荐

    如何在Flex中使用profile的教程

    - **Garbage Collection and Loitering Objects**:垃圾回收情况及徘徊对象的信息。 #### 六、优化决策 虽然Adobe Flex Profiler能够提供大量的性能数据,但它并不会直接告诉您如何优化应用。优化决策需要开发者...

    Flex垃圾回收机制

    垃圾回收(Garbage Collection,简称GC)是一种自动的内存管理技术,其目的是识别并释放不再使用的对象所占用的内存空间。在Flex中,当一个对象没有被任何变量引用时,垃圾回收器会识别这个对象为“垃圾”,然后...

    Flex虚拟机内存管理机制及防止内存泄漏

    Flex虚拟机采用了一种自动垃圾回收(Garbage Collection, GC)的内存管理系统,它负责监控和释放不再使用的内存空间。垃圾回收的主要目标是确保不再被程序引用的对象能够被有效地释放,以便为新对象腾出内存。 在...

    Flex 有效的内存回收方法

    1. **垃圾收集(Garbage Collection)**: 垃圾收集是Flex中实现内存管理的主要机制。它自动追踪并释放不再使用的对象所占用的内存。理解如何与垃圾收集器协同工作是减少内存问题的关键。开发者应确保不持有对不再...

    flex内存泄露(转载)

    如同其他高级编程语言一样,AVM内嵌有垃圾收集器(Garbage Collection),用于自动管理和释放不再使用的对象所占用的内存资源。尽管如此,Flex应用仍然可能出现内存泄露问题,这是由特定的编程实践或设计缺陷引起的...

    深入FLEX组件生命周期

    Garbage Collection(垃圾回收) **定义**:当组件不再被任何引用指向时,它将成为垃圾回收的目标。为了确保组件能够被正确回收,需要避免使用强引用(如事件监听器、字典和定时器等)。 **代码示例**: ```as //...

    Flex内存管理及相关内容

    Flex作为一种用于构建RIA(Rich Internet Applications)的应用框架,其背后的编程语言ActionScript(简称AS)支持垃圾回收(Garbage Collection, GC)。这使得开发者无需手动管理内存,从而减少了一些常见的内存...

    flash关于内存管理与内存管理

    内存管理是编程中的关键环节,尤其在Flash和ActionScript(AS)开发中,垃圾回收(Garbage Collection,GC)机制是防止内存泄露的关键。Flash Player的内存管理主要依赖于其内部的AVM(ActionScript Virtual Machine...

    纯as3.0flash游戏 坦克大战 源码

    9. **优化技巧**:为了提高游戏性能,源码可能包含了缓存(caching)、垃圾回收管理(garbage collection)、绘制优化(rendering optimization)等策略。 10. **调试和测试**:源码中可能包含了一些调试工具和日志...

    2015年编译原理期中试题1

    静态存储管理包括栈和堆分配,而动态存储管理包括垃圾回收(Garbage Collection)和手动内存管理。 5. **编译方式与解释方式的区别**:编译方式是将源代码一次性转换为目标代码,然后执行目标代码;解释方式则是...

    Desktop.zip

    垃圾回收(Garbage Collection, GC)是自动内存管理的一种方式,主要用于处理程序中不再使用的对象,防止内存泄漏。Java、Python和.NET等编程语言都内置了垃圾回收机制。主要的垃圾回收方法有标记-清除、复制、标记-...

Global site tag (gtag.js) - Google Analytics