让你的AS3程序内存占用永远是人家程序的零头

明显是夸张了点,不过这篇文章的确可以让大家的AS3应用的内存占用保持在一个较低的水平。



先是羡慕一下徐灿在苏州第二大的IT公司游戏蜗牛里面当上实习生了,再鄙视一下他在三天里面总结出这些经验,最后是叹一下气为什么这篇总结性的文章非要我写。

测试数据是我做的,不过时间不多,所以只能做到一点点数据,如果谁有耐心的话,可以接着来做更详细的测试。

在flashPlayer里面,我们面临着两个问题:

1.不知道什么时候才会出现的GC

2.内存泄露

个人认为,flashPlayer内存占用高很大程度上不是因为无法手动GC,而是因为设计上的失误(是天真地以为flash/flex像C#/java那样有防止内存泄露的完善的机制)而导致无穷无尽的内存占用。如果你经常被这些问题困扰,那么你有幸了,因为你遇到了猫粮,遇到了能帮你把应用内存占用降下来的文章。

这篇文章讨论了一下几个问题:
1.删除对象是否要将对象设置为null的问题
2.外部文件的处理
3.事件监听器的处理
4.viewStack的bug。

没发完前请勿插楼

[ 本帖最后由 猫粮 于 2007-10-23 12:53 编辑 ]

我也来说两句 查看全部回复
最新回复
猫粮 (2007-10-23 12:57:37)
为了测试环境的纯净,在数据输出方面我只使用了Trace。
下面是MemoryMonitor的代码:(可怜徐灿的代码被我整容了...大概只保留了定时器还有CallBackFunction)
这个东西主要用于每隔一秒就检测一次内存,并且执行一次callBackFunction。
CODE:

<?xml version="1.0" encoding="UTF-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="start()">
<mx:Script>
<![CDATA[
import flash.utils.getTimer;
private var timer:Timer;
public var interval:int = 1000;
public var callbackFunction:Function = null;
private function timerHandler(event:TimerEvent):void
{
trace("Time:"+getTimer()+"cur:"+System.totalMemory)
if (callbackFunction != null)
callbackFunction();
}
public function start():void
{
timer = new Timer(interval);
timer.addEventListener("timer", timerHandler);
timer.start();
}
public function stop():void
{
timer.stop();
timer.removeEventListener("timer", timerHandler);
timer = null;
}
]]>
</mx:Script>
</mx:Canvas>
猫粮 (2007-10-23 13:01:23)
这个是在测试过程中进行内存回收的代码
这个是天下人都知道的AS-Hack了。顺便提一下,这个东西执行越多次效果越好...一晚十次郎...
徐灿的内存回收得代码又被我改成类了....米哈哈

MyGC
CODE:

package
{
import flash.net.LocalConnection;
public class MyGC
{
public static function GC()
{
try
{
var lc1:LocalConnection = new LocalConnection();
var lc2:LocalConnection = new LocalConnection();
lc1.connect('name');
lc2.connect('name2');
}
catch (e:Error)
{
}
}
}
}
猫粮 (2007-10-23 13:04:33)
这个就是上面提到的两贴代码的宿主了。我们只需要更改enterFrameHandler这个函数就能对数据进行测试。
徐灿的原版代码将在最后奉上.....
CODE:

<?xml version="1.0" encoding="UTF-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
xmlns:local="*">
<mx:Script>
<![CDATA[
import mx.controls.VideoDisplay;
private function enterFrameHandler():void
{
//TODO:测试内存占用的代码写在这里
}
]]>
</mx:Script>
<local:MemoryMonitor callbackFunction="enterFrameHandler" />
<mx:ViewStack id="abc" />
</mx:Application>
猫粮 (2007-10-23 13:06:45)
一切从Object开始,我们仅仅是新建它,所得到的数据如下图
CODE:

private function enterFrameHandler():void
{
var o:Object = new Object();
}

猫粮 (2007-10-23 13:08:17)
CODE:


private function enterFrameHandler():void
{
var o:Object = new Object();
MyGC.GC();
}

猫粮 (2007-10-23 13:13:25)
CODE:


private function enterFrameHandler():void
{
var o:Object = new Object();
o = null;
MyGC.GC();
}

猫粮 (2007-10-23 13:17:05)
private function enterFrameHandler():void
{
var flvplay:VideoDisplay = new VideoDisplay();
this.addChild(flvplay);
flvplay.source = "phone.flv";
flvplay.play();
MyGC.GC();
}

猫粮 (2007-10-23 13:18:44)
private function enterFrameHandler():void
{
var flvplay:VideoDisplay = new VideoDisplay();
this.addChild(flvplay);
flvplay.source = "phone.flv";
flvplay.play();
flvplay.close();
MyGC.GC();
}

猫粮 (2007-10-23 13:19:50)
private function enterFrameHandler():void
{
var flvplay:VideoDisplay = new VideoDisplay();
this.addChild(flvplay);
flvplay.source = "phone.flv";
flvplay.play();
this.removeChild(flvplay);
}

猫粮 (2007-10-23 13:22:45)
没有设置null版
private function enterFrameHandler():void
{
var flvplay:VideoDisplay = new VideoDisplay();
this.addChild(flvplay);
flvplay.source = "phone.flv";
flvplay.play();
flvplay.close();
this.removeChild(flvplay);
MyGC.GC();
}

设置null版
private function enterFrameHandler():void
{
var flvplay:VideoDisplay = new VideoDisplay();
this.addChild(flvplay);
flvplay.source = "phone.flv";
flvplay.play();
flvplay.close();
this.removeChild(flvplay);
flvplay = null;
MyGC.GC();
}

猫粮 (2007-10-23 13:23:58)
private function enterFrameHandler():void
{
var s:String = Math.random().toString();
this.addEventListener(s,abc);
function abc(){};
}

猫粮 (2007-10-23 13:25:11)
private function enterFrameHandler():void
{
var s:String = Math.random().toString();
this.addEventListener(s,abc);
MyGC.GC();
function abc(){}
}

猫粮 (2007-10-23 13:27:21)
欲知后事如何....请自行测试...
莫非这里我粘错测试数据了...
private function enterFrameHandler():void
{
var s:String = Math.random().toString();
this.addEventListener(s,abc);
this.removeEventListener(s,abc);
function abc(){}
}

猫粮 (2007-10-23 13:28:47)
这个最搞笑,越来越少越来越少......
private function enterFrameHandler():void
{
var s:String = Math.random().toString();
this.addEventListener(s,abc);
this.removeEventListener(s,abc);
function abc(){}
MyGC.GC();
}

猫粮 (2007-10-23 13:31:11)
上面的是Flex3 SDK的,下面的是Flex2 Hotfix3的SDK
徐灿说Flex2SDK的viewStack有bug,但是这样测试好像看不出什么问题..大家如果想深究的话就要自己测试一下
当然代码里面能发现问题,这些就不好说了..

private function enterFrameHandler():void
{
var flvplay:VideoDisplay = new VideoDisplay();
abc.addChild(flvplay);
flvplay.source = "phone.flv";
flvplay.play();
flvplay.close();
abc.removeChild(flvplay);
MyGC.GC();
}

猫粮 (2007-10-23 13:33:52)
这次的测试就暂时到这里
我个人的感觉就是:
1.开了什么就要关掉什么
2.设置为null这一做法是没啥作用的,有没有被引用系统自己清楚,自己YY也没用
3.GC长做,特别是在清理的时候,这样能保证内存在第一时间被回收。
希望本文能对大家有点帮助
猫粮 (2007-10-23 13:39:36)
很抱歉我篡改了你那么多东西,现在把你本人生平的所讲所写也附上........

′.雨﹖ 15:53:13
其中有几个要点
′.雨﹖ 15:58:12
关于视频的,就是必须close了再new才能保证flv已经占的内存被释放……不然会造成内存泄露。

任何新addChild进来的东西关闭的时候都要removeChild掉。

还有就是FLEX 2 SDK里只要牵扯到ViewStack的组件都有先天性的内存泄露。这个问题在FLEX 3 SDK中得到了解决。

使用Module的要注意,不是只要unload了模块就等于把里面全部资源都释放了。必须把里面的东西手动清除。

比如我那个例子里面的,都removeAllChildren了。如果module里有正在动的东西或者什么的,他光unload那个module只是说明把他从显示上去掉,里面的东西没有消除引用,所以必须unload的时候也把module里的东西removeAllChildren了

′.雨﹖ 16:04:12
如果发生内存泄露,他就不回收了…
′.雨﹖ 16:07:31
其实最主要的就是防止内存泄露,及时不及时回收内存只是其次
′.雨﹖ 16:58:44
……引用页http://blogs.adobe.com/aharui/20 ... ion_and_memory.html

其他有什么得罪的您老人家就原谅我吧...
ML.rar
(2007-10-23 13:39:36, Size: 605 KB, Downloads: 70) 

 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值