9RIA.com天地会 - 论坛

返回列表 发帖

天地培训

9RIA天地会官方培训机构

Adobe官方认证培训中心

让你的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 编辑 ]
1

评分人数

  • 黑羽

黑羽 赐本贴 威望 + 8  诏曰: 用心!好文!^^

天地人才库

测试环境的建立

为了测试环境的纯净,在数据输出方面我只使用了Trace。
下面是MemoryMonitor的代码:(可怜徐灿的代码被我整容了...大概只保留了定时器还有CallBackFunction)
这个东西主要用于每隔一秒就检测一次内存,并且执行一次callBackFunction。
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml"
  3.     creationComplete="start()">
  4. <mx:Script>
  5. <![CDATA[
  6.     import flash.utils.getTimer;
  7.     private var timer:Timer;
  8.     public var interval:int = 1000;
  9.     public var callbackFunction:Function = null;
  10.     private function timerHandler(event:TimerEvent):void
  11.     {
  12.         trace("Time:"+getTimer()+"cur:"+System.totalMemory)
  13.         if (callbackFunction != null)
  14.             callbackFunction();
  15.     }
  16.     public function start():void
  17.     {
  18.         timer = new Timer(interval);
  19.         timer.addEventListener("timer", timerHandler);
  20.         timer.start();
  21.     }
  22.     public function stop():void
  23.     {
  24.         timer.stop();
  25.         timer.removeEventListener("timer", timerHandler);
  26.         timer = null;
  27.     }
  28. ]]>
  29. </mx:Script>
  30. </mx:Canvas>
复制代码

TOP

强制内存回收

这个是在测试过程中进行内存回收的代码
这个是天下人都知道的AS-Hack了。顺便提一下,这个东西执行越多次效果越好...一晚十次郎...
徐灿的内存回收得代码又被我改成类了....米哈哈

MyGC
  1. package
  2. {
  3.     import flash.net.LocalConnection;
  4.     public class MyGC
  5.     {
  6.         public static function GC()
  7.         {
  8.             try
  9.             {
  10.                 var lc1:LocalConnection = new LocalConnection();
  11.                 var lc2:LocalConnection = new LocalConnection();
  12.                 lc1.connect('name');
  13.                 lc2.connect('name2');
  14.             }
  15.             catch (e:Error)
  16.             {
  17.             }
  18.         }
  19.     }
  20. }
复制代码

TOP

好兄弟,讲义气!---by eko

踏上天地会荣耀之路!

 

申请舵主

加入掘金队

加入译林军

知识专题整理

 

咨询(QQ):

1442604479(小地)

 

主程序代码

这个就是上面提到的两贴代码的宿主了。我们只需要更改enterFrameHandler这个函数就能对数据进行测试。
徐灿的原版代码将在最后奉上.....

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
  3.     xmlns:local="*">
  4.     <mx:Script>
  5.         <![CDATA[
  6.             import mx.controls.VideoDisplay;
  7.             private function enterFrameHandler():void
  8.             {
  9.                 //TODO:测试内存占用的代码写在这里
  10.         }            
  11.         ]]>
  12.     </mx:Script>
  13. <local:MemoryMonitor callbackFunction="enterFrameHandler" />
  14.   <mx:ViewStack id="abc" />
  15. </mx:Application>
复制代码

TOP

不断新建Object的Fp内存占用

一切从Object开始,我们仅仅是新建它,所得到的数据如下图

  1. private function enterFrameHandler():void
  2. {
  3. var o:Object = new Object();
  4. }
复制代码

TOP

新建Object+内存回收


  1. private function enterFrameHandler():void
  2. {
  3. var o:Object = new Object();
  4. MyGC.GC();
  5. }
复制代码

TOP

内存回收+设置为null的flash内存占用


  1. private function enterFrameHandler():void
  2. {
  3. var o:Object = new Object();
  4. o = null;
  5. MyGC.GC();
  6. }
复制代码

TOP

加载外部文件,不关闭,内存回收

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

TOP

关闭外部文件但是不移除显示对象

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

TOP

只移除显示对象

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

TOP

彻底清除引用的对比

没有设置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();
}

TOP

不断添加监听器

private function enterFrameHandler():void
{
var s:String = Math.random().toString();
this.addEventListener(s,abc);
function abc(){};
}

TOP

添加监听器+内存回收

private function enterFrameHandler():void
{
var s:String = Math.random().toString();
this.addEventListener(s,abc);
MyGC.GC();
function abc(){}
}

TOP

添加后移除监听器

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

TOP

添加+移除+内存回收

这个最搞笑,越来越少越来越少......
private function enterFrameHandler():void
{
var s:String = Math.random().toString();
this.addEventListener(s,abc);
this.removeEventListener(s,abc);
function abc(){}
MyGC.GC();
}

TOP

返回列表