请选择 进入手机版 | 继续访问电脑版
收藏本站腾讯微博新浪微博
点点网模板设计大赛 phpchina

经典论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

蓝色理想 最新研发动态 用悬赏 三天解决问题 解决访问速度慢 论坛支持农历生日 - 给官方提建议

论坛活动及任务 归纳网站最新活动 地图任务 邮件更新任务:保护帐号安全

积分换实物,来参加蓝色理想积分兑换吧! 联系招聘客服 蓝色理想帮你找工作! 万元奖励等你拿——点点网模板设计大赛

查看: 7518|回复: 8

[AS3] AS3日积月累(3) - 利用AS3的图形界面开发及资源管理攻略 [复制链接]

awflasher 楼主
帖子
1219
体力
5975
威望
234
发表于 2007-5-13 00:48:43 |显示全部楼层
as3blog.com日积月累系列全部为原创,转载请保留:http://as3blog.com/as3/as3tip-take-care-of-resource

摒弃了attachMovie之后的AS3,采用了类似DOM的操作方式。addChild、removeChild、getChildAt等方法开始成为AS3中显示(在屏幕上渲染)、操作图形的主要方法。由于AS1、AS2完全是依赖于attchMovie的思想,因此对于传统Flash开发人员来说,转变到新的addChild的确需要下一番功夫。

由于新的“DisplayObject”在内存的使用上非常“敏感”。往往由于不良的编程习惯会造成不必要的内存泄漏,因此,我们不得不比AS1、 AS2时代更加深入到内存管理了。我想,每一个Flash开发人员,包括我自己,都应该花一番功夫仔细体会“内存管理”这几个字的含义。毕竟我们学习 AS3是为了开发比AS1、2时代更加先进、高效而且内存占用小的应用程序,如果还是开发一些简单的应用,也就失去我们每一个人使用AS3的意义了。

我觉得,由于GC是Flash应用程序内存管理的核心,我应该先从AS3中的Garbage Collector(简称GC)开始说起。AS3的GC功能比AS1、2中的要强大的多。然而,强大的同时,也带来了一定程度的复杂性。但是也不至于非常复杂,我觉得比C++等传统语言要容易掌握得多。

在研究内存如何回收之前,先说一下变量的创建:
在Flash中,我们每建立一个非原生变量时(Boolean, String, Number, uint, int这些是原生变量),这个变量名只是一个reference(指向,有时候也成为“引用”)而已,而并非这个变量本身。例如:
var a:int = 5; //a就是5
var b:int = a; //b是a,也就是5
a = 4;
trace(b); // 是5,而不是4!
//改变b的值,a不发生变化。反之亦然
var c:Object = {name:”aw”, blog:”www.awflasher.com/blog”}; //c只是指向一个内部的Object,为了描述方便,称其为“O”
var d:Object = c; //d指向c,指向了同一个Object“O”
c.name = “bw”
trace(d.name); //不是aw,而是bw了
//改变c也好,改变d也罢,其实是改变了那个“O”,因此改变c的时候,d的值也就变了。因此d.name已经被改变为了“bw”。

首先,明确一点,GC会按照一定的时间周期进行内存清理(memory sweep)。因此不要因为delete掉一个object后检查System.totalMemory内存就没有反应而怀疑GC是否正常。

那么GC为什么要按照一定的时间周期进行清理呢。这还要得从GC的具体工作原理说起。

GC的两个回收体系:
1、“Reference Counting” - 引用计数器
这个体系是自从AS1时代就有的体系,它的工作原理非常简单:系统计算每一个对象被指向,或者说引用的次数。比如
var a:Object = {name:”aw”, blog:”www.awflasher.com/blog”};
这时候,这个Object(我们仍然称为“O”),有一次引用,它的引用计数器为1(来自a)。
我们再建立一个对象b,并指向到a:
var b:Object = a;
这时候“O”引用计数器变为了2(来自a、b)
我们删除一个,比如先删除b:
delete b;
这时候引用计数器为(2-1=1)1,GC不操作
再删除另外一个a:
delete a;
“O”引用计数器变为(1-1=0)0,GC出面干掉这个对象。
这套体系很轻便,CPU压力较小。但是它也有缺陷。当我们的对象内部互相引用的时候,麻烦就来了。例如:
var a:Object = {name:”aw”, description:”unknown”};
// 建立一个对象a,仍然假设内部对象为“O”,这时O的引用次数为1
var b:Object = {nameObj:a, url:”awflasher.com”};
// b引用了a,同时创建了新的内部对象“P”。这时O的引用次数为2,P为1
a.myDescription = b;
// a的myDescription属性指向到了b。这样,P的引用次数也为2了。
// 是不是有点头晕?静下来,画个图慢慢看看:)
delete a;
delete b;
两次delete操作后,O、P的引用次数都是1,它们将继续占用你的内存。“Reference Counting” 体系无能为力了。

2、“Mark Sweeping” - 标记清除法则
GC的第一种机制“Reference Counting”,在FlashPlayer8之前是GC唯一的机制。FlashPlayer6和7由于引入了复杂的OOP开发模式,尤其是7引入了类似Java、C++等强大OOP语言的语法。利用Flash设计的复杂项目越来越多。由于Flash开发人员大多不了解GC,而Java、C++的开发人员又已经习惯了强大的GC(无论是自动的还是手动的)。因此FlashPlayer6、7的内存问题开始浮现出来。
Okay,Flash Player8引入了新的“Mark Sweeping”机制。我想这也是当年Marcomedia(Adobe)基于退出Player8的原因吧!(还记得当年Flash8的介绍视频么,效率提高是一个革命性的改进)
下面就来讲述“Mark Sweeping” - 标记清除法则的工作原理。
FlashPlayer会从root开始,遍历系统的每一个变量,并对有指向的对象之间,记录一次联系。在遍历结束之后,凡是与root不相联系的对象,被FlashPlayer无情地干掉:)
Okay,回到刚才的例子,当我们delete a,并delete b之后,root与O、P就划清了界线。这时候,GC就可以进行一次肃清了。
然而,由于这种“Mark Sweeping”要遍历所有的对象,因此非常消耗资源。这也就回到了当初的问题:“GC为什么要按照一定的时间周期进行清理“ - 因为不能给CPU造成太大的负担。
我个人猜测,GC的内部清除策略应该是在某一次事件(例如delete)发生后,在CPU比较空闲、RAM分配相对合理的情况下执行的。

Okay,不要以为有了“Mark Sweeping”就万事大吉了。由于GC不会即时进行,因此你的对象会在一段时间内“阴魂不散”!对于一个追求完美的开发人员来说,这意味着它们内部的某些机制会在被删除之后继续工作:AS语句会继续执行、声音会继续播放、事件会继续触发!

KirupaForum有网友说,“All you got to do is pray the garbage collector doesn’t break down.”,确实,如果一个应用程序要运行上一个多小时,那么慢慢流逝的内存会让你的用户对你的产品失望(例如游戏)。因此我们需要有一个良好的资源管理策略。

待续……
西部数码顶级域名注册商39元抢注!
orcsor 
帖子
237
体力
336
威望
0
居住地
四川省 成都市
发表于 2007-5-13 02:19:50 |显示全部楼层
aw 厉害啊 这么晚了 顶你
http://www.5ucai.com
无忧素材网
租服务器,上51IDC | [长沙]招聘:PHP经理10K/WEB前端6K/PHP开发6K

使用道具 举报

eidiot 
帖子
258
体力
671
威望
101
发表于 2007-5-13 07:03:52 |显示全部楼层
严重待续

使用道具 举报

黑羽翔天

金牌会员

帖子
450
体力
2731
威望
399
发表于 2007-5-13 12:58:33 |显示全部楼层
我喜欢这种带有学术味道的帖子。支持aw一把。

有个错误一定要指出:
delete在AS3中用法有重大改变,不能用来删除对象,只能用在删除动态属性上。
因此,你的例子不成立,会报错:
  1. var a:Object = {name:"aw", blog:"www.awflasher.com/blog"};
  2. var b:Object = a;
  3. delete b;
  4. //报错:1189: Attempt to delete the fixed property a.  Only dynamically defined properties can be deleted.
  5. delete a;
  6. //报错:1189: Attempt to delete the fixed property a.  Only dynamically defined properties can be deleted.
复制代码

在AS3中要删除对象只能使用
  1. b= null;
  2. a= null;
复制代码
黑羽翔天◎足下八邦
欢迎来我的博客 :)
www.kingda.org  (AS3教程)

使用道具 举报

黑羽翔天

金牌会员

帖子
450
体力
2731
威望
399
发表于 2007-5-13 13:08:07 |显示全部楼层
另外关于垃圾回收机制,aw介绍的是两种已经成熟的垃圾回收理论。前段时间,看了AVM代码后,我发现AVM同时采用了这两种方式,和目前其他强大的OOP语言一致。
而且还要复杂一些。
由于加入了对弱引用的支持,AVM2的垃圾回收机制更加强大。AVM中使用了GCFinalizedObject来表示要回收的对象,而其子类GCWeakRef就是用来处理弱引用对象的。

至于何时回收,机制比较复杂。我看到代码中是和堆的分配联系在一块儿的。堆的状态符合算法要求后,才开始进行垃圾回收。一种比较常见的外部表现是:可能到了程序占用一定数量的内存后,反复震荡,这个时候就是垃圾回收机制在工作了。
各位有兴趣的可以使用每隔一点时间连续不断的创建一定size的匿名位图对象,来测试垃圾回收的表现。

[ 本帖最后由 KingdaSun 于 2007-5-13 13:09 编辑 ]
黑羽翔天◎足下八邦
欢迎来我的博客 :)
www.kingda.org  (AS3教程)

使用道具 举报

帖子
270
体力
612
威望
0
居住地
河北省 承德市
发表于 2007-5-14 13:16:13 |显示全部楼层
好东西
没完的吧.待续

使用道具 举报

帖子
7
体力
24
威望
0
发表于 2007-5-14 20:38:22 |显示全部楼层
Orz....
不懂不懂....
膜拜楼上各位老大ing....

使用道具 举报

kys777 
帖子
55
体力
66
威望
0
发表于 2007-5-14 21:47:06 |显示全部楼层
好像GC并不是按照一定的时间周期进行内存清理的。
垃圾回收是一项比较耗费资源的操作,
不到需要的时候是不会自动去执行的。

使用道具 举报

弃天笑

高级会员

帖子
303
体力
1246
威望
0
居住地
广东省 广州市
发表于 2007-9-28 10:06:39 |显示全部楼层
提醒:最后回贴距现在137天,请不要无意义回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

Archiver|手机版|安久科技提供CDN|blueidea.com ( 京ICP备05002321号 )  

GMT+8, 2012-2-13 13:16 , Processed in 0.102575 second(s), 8 queries , Gzip On, Memcache On.

Powered by Discuz! X2

© 2001-2011 Comsenz Inc.

回顶部