跳到主要內容

ActionScript 3.0 記憶體釋放問題

一個好的Flash作品, 除了要有美美的設計與酷炫的動態外更重要的應該是效能。
就以一個EnterFrame事件來說明好了。
在ActionScript2.0時, MovieClip的EnterFrame事件, 當該MovieClip被移除時
其事件也會自動消失。
但在ActionScript3.0, 把該MoviecClip移除, EnterFrame還是會在。
所以當你載入越多的swf檔時, 沒有把前一個swf事件都移除的話, 效能就會越來越差。
那要如何移除事件呢?



//偵聽 
clip.addEventListener(事件類型:String , 偵聽者函式:Function) 
//取消偵聽 
clip.removeEventListener(事件類型:String , 偵聽者函式:Function);


那什麼時候要取消偵聽?
通常在移除可視物件時, 就要把所有的事件都取消掉, 這樣才不會一直佔住記憶體。
可視物件有個Event.REMOVE_FROM_STAGE可以加以利用
當物件被從stage移除時, 會廣播該事件。
當偵聽者聽到時, 就把所有有註冊的事件通通取消掉。

被載入的Loaded.swf
在建構函式時就偵聽Event.ENTER_FRAME事件。

package  {   
import flash.display.Sprite; 
import flash.events.Event; 
public class Loaded extends Sprite{   
  public function Loaded() { 
   this.addEventListener(Event.ENTER_FRAME, onEventEnterFrame); 
  }   
  private function onEventEnterFrame(e:Event):void { 
   trace(e); 
  }   
} 
}



載入的主要SWF

package  {   
import com.bit101.components.PushButton; 
import flash.display.Loader; 
import flash.display.Sprite; 
import flash.events.Event; 
import flash.events.MouseEvent; 
import flash.net.URLRequest; 
[SWF(width = "950", height = "500", frameRate = "41", backgroundColor = "#000000", pageTitle = "milkmidi.com")] 
public class Main extends Sprite{   
  private var _ldr:Loader 
  public function Main() { 
   _ldr = new Loader(); 
   _ldr.load(new URLRequest("Loaded.swf"));    
this.addChild(_ldr); 
   var _btn:PushButton = new PushButton(this, 0, 0, "unload", onClick);    
  }   
  private function onClick(e:MouseEvent):void{ 
   _ldr.unload(); 
  }   
} 
}



發怖成功後, 可以看到面版不斷的輸出文字,
按下按鈕 ,unload該swf, 還是看到面版不斷的輸出文字, 也就表示物件移除
不代表事件移除, 所以我們改寫一下Loaded.swf的程式碼。

package  {   
import flash.display.Sprite; 
import flash.events.Event; 
public class Loaded extends Sprite{   
  public function Loaded() { 
   this.addEventListener(Event.ADDED_TO_STAGE, onAdd2Stage); 
   //當可視物件被加入至場景後, 會發出的事件。 
   this.addEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage);    
   //當可視物件被移除後至場景, 會發出的事件。 
  }    
  private function onRemovedFromStage(e:Event):void { 
   //物件被移除, 所有有偵聽的事件也要手動取消掉。    
   this.removeEventListener(Event.ADDED_TO_STAGE, onAdd2Stage); 
   this.removeEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage); 
   this.removeEventListener(Event.ENTER_FRAME, onEventEnterFrame); 
  }   
  private function onAdd2Stage(e:Event):void { 
   this.addEventListener(Event.ENTER_FRAME, onEventEnterFrame); 
  } 
  private function onEventEnterFrame(e:Event):void { 
   trace(e); 
  }   
} 
}



這樣當物件被除掉後, 也可以一起把事件都取消掉

補充一下:
在google找了些相關資訊, 發現一種不正規的Hack方法
但真的能將記憶體給釋放:

import flash.net.LocalConnection; 
import flash.system.System; 
try{ 
new LocalConnection().connect("foo"); 
new LocalConnection().connect("foo"); 
}catch(error : Error){ 
} 
//透過try catch,讓Player的garbage collection強製他回收不用的記憶體 
System.gc(); 
//強制執行記憶體回收程序



經過不小心google一下
發現這樣的做法是一種不正規的Hack方法
但真的能清掉記憶體
試試看再補上一句

try{ 
new LocalConnection().connect("foo"); 
new LocalConnection().connect("foo"); 
}catch(error : Error){ 
} 
System.gc();


這樣能清的更乾淨

留言

這個網誌中的熱門文章

自訂Apache的日誌檔輪替(Custom Apache log rotation behaviour on CentOS / RHEL)

1. 若有設定虛擬主機的話,要先設定虛擬主機的日誌以及日誌內容的格式 <VirtualHost *:80> ServerName DNS網址 DocumentRoot 網站目錄路徑 LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" combined CustomLog access_log的路徑 combined </VirtualHost> ... ... ... 其中 LogFormat 與 CustomLog 的制定方式,在官方頁面有說明「 Log Files說明頁面 」 2. apache的日誌設定完之後,就可以開始設定apache的logrotate功能。在開始定義之前,先解釋甚麼是logrotate。 logrotate顧名思義就是log rotate,即日誌的輪換。Logrotate是Linux系統自身帶的一個日誌輪替執行檔,它的執行檔所在的目錄是/usr/sbin/logrotate,是專門對各種系統日誌(syslogd,mail)進行輪替的執行檔。 所以logrotate 的主要功能就是將舊的日誌檔案移動成舊日誌檔, 並且重新建立一個新的空的日誌檔案來記錄,它的執行結果有點類似底下的圖示:

巨型網站的分散式架構設計 (雲端運算的基礎)

網站初始: 架設網站入門其實很容易,很多網路上的免費資源運用一下,許多學生也可以自己建置網站,最基本的架構就是安裝一台Web server 及一台Database server,這樣的架構在流量不高的個人網站的確已足夠,但其實風險相當高,因為完全沒考慮到日後的擴充性(scalibility),也沒考慮到系統容錯及復原能力(High avability & Failover),因此只要流量一高,問題就接踵而至,但用這個架構可視為Close beta時期,多找一些親友來當免費測試員。 商業化架構: 在這時期代表已經籌到一筆資金,網站可以進行商業化架構設計,一般商業化考量下的標準架構,通常如下圖所示:

透過awk程式來計算網站流量

網路上有很多很多計算網站流量的分析工具....但是有時後自己想要知道如何分析,所以在網路上找到此指令可以計算網站的流量。 65.55.213.67 - - [04/Jul/2013:04:37:51 +0800] "GET /user.php?act=login HTTP/1.1" 200 10104 "-" "msnbot/2.0b (+http://search.msn.com/msnbot.htm)" 65.55.213.67 - - [04/Jul/2013:04:37:53 +0800] "GET /category.php?id=3 HTTP/1.1" 200 16041 "-" "msnbot/2.0b (+http://search.msn.com/msnbot.htm)" 65.55.213.67 - - [04/Jul/2013:04:37:56 +0800] "GET /category.php?id=1 HTTP/1.1" 200 11080 "-" "msnbot/2.0b (+http://search.msn.com/msnbot.htm)" 65.55.213.67 - - [04/Jul/2013:04:37:58 +0800] "GET /goods.php?id=351 HTTP/1.1" 200 19369 "-" "msnbot/2.0b (+http://search.msn.com/msnbot.htm)" 以上是從access_log擷取一部分的內容 再透過以下指令,就能計算出網站流量 cat /網站日誌檔目錄/access_log | awk '{SUM+=$10}END{print SUM/1024/1024}' 得出的流量數據是 0.054MB,因為流量數據是byte單位所以要除2次1024byte(56594/1024/1024) 其中 awk 是一種處理資料且可產生報告的語言,功能相當強大:而處理的單位是一行一行的比對處理,當符合awk的條件