“FlashPlatform GC”的版本间的差异

来自Blueidea
跳转至: 导航搜索
垃圾回收機制
計數法
 
(未显示同一用户的17个中间版本)
第10行: 第10行:
 
   [[Image:FlashPlatform_Numbers2.jpg]]mark and sweep 標記並清除,在DOM種從root向下遍歷並標記。清除沒有被標記的。
 
   [[Image:FlashPlatform_Numbers2.jpg]]mark and sweep 標記並清除,在DOM種從root向下遍歷並標記。清除沒有被標記的。
  
計數法<br/>
+
==計數法==
通常用來描述垃圾回收機制但並為作為唯一的回收手段。<br/>
+
通常用來描述垃圾回收機制但並未作為唯一的回收手段。<br/>
<center>[[Image:FlashPlatform_GC_count.png]]</center><br/>
+
  優點:快速。並不會帶來大的CPU開銷。
按照標記清除法。清理的結果是這樣。<br/>
+
  缺點:並不能回收完所有用戶不再使用的對象。
<center>[[Image:FlashPlatform_GC_count2.png]]</center><br/>
+
 
 +
 
 
遺憾的是計數法有它的局限性。因為
 
遺憾的是計數法有它的局限性。因為
 
   如果不手動釋放引用。那麼對象將無法回收。
 
   如果不手動釋放引用。那麼對象將無法回收。
第32行: 第33行:
 
</syntaxhighlight>
 
</syntaxhighlight>
 
   對象引用沒有清除為null它還指向具體對象內存地址。
 
   對象引用沒有清除為null它還指向具體對象內存地址。
   對象的引用計數為1。無法被清除。離開函數後。我們只是無法訪問到這個對象。但引用和對象都還存在。
+
   對象的引用計數為1。無法被清除。離開函數後。我們不再有任何從應用程序訪問這個對象的方式。但引用和對象都還存在。
 
   因此計數法通常容易去描述垃圾回收機制。但並未使用在所有語言。
 
   因此計數法通常容易去描述垃圾回收機制。但並未使用在所有語言。
 +
 +
 +
計數法為甚麼不能清除所有不使用的物體。<br/>
 +
 +
 +
 +
<center>首先一個對象是怎樣的。對象一般在堆中存放。</center><br/>
 +
<center>[[Image:FlashPlatform_ObjectWhatLike.png]]</center><br/>
 +
<center>上述代碼為例a引用和對象都處於無法訪問到的狀態,但有引用指向,其計數不為0所以無法釋放</center><br/>
 +
<center>[[Image:FlashPlatform_GC_countdetail1.png]]</center><br/>
 +
 +
<center>實際情況有可能更加複雜</center><br/>
 +
<center>幾個對象相互引用。計數都不為零,那麼無法回收了。</center><br/>
 +
<center>[[Image:FlashPlatform_GC_countdetail2.png]]</center><br/>
 +
 +
==標記清除法==
 +
這一辦法正是為了解決這一問題,從ActionScript 3.0(和Flash Player 8)開始,<br/>
 +
垃圾回收器使用標記和清除的方法來查找程序中的非活動對象。<br/>
 +
因此對於上面的情況。不再使用到的對象都會被幹死。<br/>
 +
  優先:清除不使用對象,徹底。
 +
  缺點:比較耗費資源,因此只有必要時刻才會調度。
 +
 +
 +
工作原理
 +
  首先從root出發查找對象。並將對象標記為active活動物體。然後查找所有對象中引用所指向的對象。
 +
  不斷重複這一過程直到無法找到後續對象。
 +
那麼這樣就分開了active活動對象和inactive非活動對象。(圖中綠色為活動物體,黑色為非活動物體)<br/>
 +
<center>[[Image:FlashPlatform_GC_mark.png]]</center><br/>
 +
 +
然後幹死非活動對象就可以了。
 +
 +
==重點==
 +
甚麼時候垃圾回收會執行。
 +
  簡單的說。當提供Flash的內存快不夠用的時候。垃圾回收器會過來看看有甚麼能做的。
 +
 +
 +
雖然FlashPlayer並沒有提供Release版本的API讓用戶去主動調用垃圾回收器。
 +
當然用戶也的確沒有必要去主動調用,它原本就是被設計成這樣。
 +
有一些非官方手段來強制調用
 +
<syntaxhighlight lang="actionscript">
 +
new LocalConnection().connect("gc");
 +
new LocalConnection().connect("gc");
 +
</syntaxhighlight>
 +
這不能作為您的救命稻草。說不定下一個版本如此就不可行了也說不定呢。<br>
 +
 +
  唯一可行並行之有效的辦法
 +
  是讓你的對象可以被回收,而不去關心它何時何地被回收。
 +
 +
 +
通常。當你頻繁的去創建一個物體而並不永久性使用。<br>
 +
那麼這個內存持續增長後再某一時刻會將它們釋放。<br>
 +
但如果對象數量巨大。回收是耗費資源的。因此很多程序一定時間後會卡一下。<br>
 +
對於此點。可以採用以下方式改進<br>
 +
  對象復用,將不需要使用的對象換存起來。如果再需要此對象,不需重新創建,直接從換存種取出重新設定參數即可。
 +
  換存可以使用ActionScript3的弱引用緩存機制建立對象池,將對象存在Dictionary的key中。
 +
為甚麼要減少new對象的操作<br>
 +
  創建對象意味分配內存。比普通數學計算或者是引用指向要慢
 +
  因此在頻繁BitmapData.copyPixels這樣類似的操作時。也推薦只使用一個Point或者Rectangle對象。總之能用一個對象就不用兩個。
 
=== 參考資料 ===
 
=== 參考資料 ===
[[http://www.adobe.com/devnet/flashplayer/articles/garbage_collection.html Flash的垃圾回收]]
+
[[http://www.adobe.com/devnet/flashplayer/articles/garbage_collection.html Flash的垃圾回收]]<br/>
 
[[http://en.wikipedia.org/wiki/Garbage_collection_(computer_science) 垃圾回收機制]]
 
[[http://en.wikipedia.org/wiki/Garbage_collection_(computer_science) 垃圾回收機制]]

2011-04-17T15:17:47的最后版本

引用和對象

首先需要達成一個共識。

 我們在ActionScript3中操作對象所使用的都是引用(指針),而非對象本身。
 所以當你刪除一個變量,被刪除的是引用。而不是對象本身。

要了解如何优化你的ActionScript 3.0代码。就需要對垃圾回收的工作原理有所瞭解。

垃圾回收機制

ActionScript3的垃圾回收機制使用兩種方式。

 FlashPlatform Numbers1.jpgreference count 如果一個對象的引用次數為0,那麼幹死。
 FlashPlatform Numbers2.jpgmark and sweep 標記並清除,在DOM種從root向下遍歷並標記。清除沒有被標記的。

計數法

通常用來描述垃圾回收機制但並未作為唯一的回收手段。

 優點:快速。並不會帶來大的CPU開銷。
 缺點:並不能回收完所有用戶不再使用的對象。


遺憾的是計數法有它的局限性。因為

 如果不手動釋放引用。那麼對象將無法回收。

假設我們在函數中創建對象

private function fun():void {
  var a:Object = new Object();
  a = null;
}

這個時候對象的引用計數為0。那麼被幹死。 但是如果

private function fun():void {
  var a:Object = new Object();
}
 對象引用沒有清除為null它還指向具體對象內存地址。
 對象的引用計數為1。無法被清除。離開函數後。我們不再有任何從應用程序訪問這個對象的方式。但引用和對象都還存在。
 因此計數法通常容易去描述垃圾回收機制。但並未使用在所有語言。


計數法為甚麼不能清除所有不使用的物體。


首先一個對象是怎樣的。對象一般在堆中存放。

FlashPlatform ObjectWhatLike.png

上述代碼為例a引用和對象都處於無法訪問到的狀態,但有引用指向,其計數不為0所以無法釋放

FlashPlatform GC countdetail1.png

實際情況有可能更加複雜

幾個對象相互引用。計數都不為零,那麼無法回收了。

FlashPlatform GC countdetail2.png

標記清除法

這一辦法正是為了解決這一問題,從ActionScript 3.0(和Flash Player 8)開始,
垃圾回收器使用標記和清除的方法來查找程序中的非活動對象。
因此對於上面的情況。不再使用到的對象都會被幹死。

 優先:清除不使用對象,徹底。
 缺點:比較耗費資源,因此只有必要時刻才會調度。


工作原理

 首先從root出發查找對象。並將對象標記為active活動物體。然後查找所有對象中引用所指向的對象。
 不斷重複這一過程直到無法找到後續對象。

那麼這樣就分開了active活動對象和inactive非活動對象。(圖中綠色為活動物體,黑色為非活動物體)

FlashPlatform GC mark.png

然後幹死非活動對象就可以了。

重點

甚麼時候垃圾回收會執行。

 簡單的說。當提供Flash的內存快不夠用的時候。垃圾回收器會過來看看有甚麼能做的。


雖然FlashPlayer並沒有提供Release版本的API讓用戶去主動調用垃圾回收器。 當然用戶也的確沒有必要去主動調用,它原本就是被設計成這樣。 有一些非官方手段來強制調用

new LocalConnection().connect("gc");
new LocalConnection().connect("gc");

這不能作為您的救命稻草。說不定下一個版本如此就不可行了也說不定呢。

 唯一可行並行之有效的辦法
 是讓你的對象可以被回收,而不去關心它何時何地被回收。


通常。當你頻繁的去創建一個物體而並不永久性使用。
那麼這個內存持續增長後再某一時刻會將它們釋放。
但如果對象數量巨大。回收是耗費資源的。因此很多程序一定時間後會卡一下。
對於此點。可以採用以下方式改進

 對象復用,將不需要使用的對象換存起來。如果再需要此對象,不需重新創建,直接從換存種取出重新設定參數即可。
 換存可以使用ActionScript3的弱引用緩存機制建立對象池,將對象存在Dictionary的key中。

為甚麼要減少new對象的操作

 創建對象意味分配內存。比普通數學計算或者是引用指向要慢
 因此在頻繁BitmapData.copyPixels這樣類似的操作時。也推薦只使用一個Point或者Rectangle對象。總之能用一個對象就不用兩個。

參考資料

[Flash的垃圾回收]
[垃圾回收機制]