Memory/reference leakage in flash player

In flex   November 29, 2006 - 12:02 pm

下面的例子示範了在 AS3 編程時,一不小心就會造成 memory leak。

Actionscript:
  1. private var p:Person;
  2.         private var arr:Array = [];
  3.    
  4.         private function init():void{
  5.             p = new Person();
  6.             p.theName = "fooooooooooooooobarrrrrrrrrrr";
  7.             this.theText.text = p.theName;
  8.             //
  9.             arr.push( p );
  10.             //
  11.             this.theList.dataProvider = arr;
  12.         }
  13.        
  14.         private function doClear():void{
  15.             p = null;
  16.             arr = null;
  17.             //this.theList.dataProvider = null;
  18.             trace("p: ", p);
  19.         }

主要的原因是:

1、FP9 的 Grabage Collection 是採用 reference counting,當一個物件生成後只要有被其它物件 reference 一次,它的 reference count 就會 +1,也就是說在下次 gc 發生時它不會被 mark and sweep。

2、以上面的例子,當一個 person instance 建立後,它被放進 arr,然後 arr 被指派為 List 的 dataProvider,這樣它就有兩個 reference counts了。

3、當執行 doClear()時,雖然將 p 設為 null,同時也清空了 arr的內容,但很不幸的,person instance 仍然存在。

4、原因是當 arr 被設為 List.dataProvider 時,在 List 內部就產生了一個 reference,這個可以從 debugging > variable 看出來,實際上在 List 裏面是產生了兩個 reference了,分別放在 source 與 list 這兩個變數裏。

這件事情的嚴重性在於,當程式執行階段要處理的 value object 非常多時,時間一久,memory leakage 就會無限擴大,而且最糟糕的是 gc 也幫不上任何忙,因此它會認為 person 還有被用到本來就不可以被清掉。

所以該怎麼辦呢?

很簡單,從現在開始起,AS3 developer 也要像 c/c++/java developer 一樣,個已負起記憶體管理的責任,心裏要清楚知道每個物件目前身處何方?它的 reference 數量?以及那些操作可能會造成reference leak?接者就是在物件不需被用到時勤快的將它們清掉。

在未來,Adobe 會推出 profiler 等工具讓 developer 可以比較輕鬆的觀察物件的生命狀態與記憶體配置,就會比較容易找出 leakage,但在那之前(預估還要半年),大家就靠自已吧...

by admin

7 Comments Add your own

  • 1. iiley&hellip  |  November 29th, 2006 at 1:21 pm

    我觉得这是再正常不过的事情了,在AS2中,也肯定是这样的。Person还存在引用,还在被List使用中,当然不会被回收。这种情况我想任何正确的垃圾回收机制都不会回收它,因为本来就不应该回收它,除非你消除所有的引用。(当然Java里面有弱引用WeeknessReference,弱引用好像是不会被count的,不知道AS3里面有没有,还不熟悉AS3)

  • 2. jeremy&hellip  |  November 29th, 2006 at 1:32 pm

    AS3 裏的 Dictionary 與 addEventListener() 有支援 weak reference, 但 AS3 language level weak reference support 據說要下一版才會放進去。

    上面這篇文章主要強調的就是:消除所有的 reference 從此變成是developer 要時時關心的事,不能以為看不見就當沒這回事 :-D

  • 3. Dreamer&hellip  |  December 1st, 2006 at 9:55 am

    这些事情对于developer出身的应该是家常便饭了,不过研究Flash很多都是designer

  • 4. jeremy&hellip  |  December 1st, 2006 at 10:27 am

    呵,我問了幾位寫java的朋友,包括[大長輩]在內,都說平常不會去特別注意這種事...

    後來進一步討論,很驚訝的發現要造成reference leakage是多麼容易的事,就算再小心,也還是有可能無意間讓它發生。

  • 5. Hiso&hellip  |  December 3rd, 2006 at 3:36 am

    我寫了一個簡單的記憶體監視器,可以試試看.

    http://www.iamhiso.com/nfblog/?p=44

  • 6. jeremy&hellip  |  December 3rd, 2006 at 10:39 am

    hiso, 那個圖表跑了一段時間後,我猜一定會出現經典的 tooth saw (鋸齒狀)圖案,因為 gc 每隔一段時會發動一次,這時 memory usage 就會 drop 下來,然後再緩慢攀伸。

  • 7. Hiso&hellip  |  December 3rd, 2006 at 3:07 pm

    啊,我那不是燒機程式,只是記憶體監看器,
    是用來看自己開發flex app,對記憶體狀況的異常控制,
    主要用來看行為操作後圖形的高低變化,
    例如對某元件重復add,remove時,是否記憶體還是直線增加,或是看使用panel或titlewindow時,那一個記憶體增加的比較多.
    可能demo的環境太單純,才沒什麼變化性.

    因為目前我只寫一種簡單監看方式,
    且為了避免記錄用的ArrayCollection變的太龐大,
    所以每到20筆資料時,就會把ArrayCollection內的資料筆數減半,檢查記憶體的時間間距加倍,轉而變長時間記憶體變化之呈現.
    至於自動gc動作,一般小程式的資料結構本來就不大,應該在圖形上的變化有限,所以我是沒特別用這程式來表現那一塊.

留言回應

hidden

您的留言會先經過站長認証後才刊登在網站上。
your comments will be approved by Administrator before appearing on the page.

Trackback this post  |  Subscribe to the comments via RSS Feed

mobile phone