flash性能優化方案整理(最全)


性能優化的原則

1.避免過早優化:太早優化將使代碼難以設計和維護,最好是針對程序的瓶頸進行優化。

2.改進性能有時需要權衡:不能一味注重改進性能,一個項目要考慮各方面的利弊,比如代碼的健壯性,結構性,擴展性,可讀性,執行效率等等。

 

把耗費CPU的計算分成小而獨立的段

 

參見:http://www.senocular.com/flash/tutorials/asyncoperations/

Flash平台是一個單線程的平台,它不支持多線程。它運行在一個循環中,以划分的“幀”為單位進行處理。幀的執行又可划分為2個階段:

(1)ActionScript 代碼的執行

(2)顯示對象(DisplayObject)的呈現

如果代碼執行的時間過長,超出了給定的timeout時限,那么Flash Player會被鎖定或者停止執行代碼,如:

[Fault] exception, information=Error: Error #1502: 腳本的執行時間已經超過了 15 秒的默認超時設置。

這時,我們需要將代碼分為小而獨立的段來進行執行。如下例

var allowedTime = 1000/fps - renderTime - otherScriptsTime;
var startTime = 0;
var savedIndex = 0;
function enterFrame() {
    startTime = getTimer();
    
    var i, n = array.length;
    for (i=savedIndex; i<n; i++){

        if (getTimer() - startTime > allowedTime){
            savedIndex = i;
            return;
        }

        process(array[i]);
    }

    complete();
}

 

使用適當的對象

 不同的對象占用的內存不同,而且不同的對象,適用的情況也不同,這時,應盡量選用占內存最小的適當對象類型。

1.選用適當的基本對象:比如int和Number,分別消耗4個和8 個字節. int 類表示的值的范圍是:-2,147,483,648 (-2^31) 到 2,147,483,647 (2^31-1),所以如果你的取值范圍在這個范圍內,最好用int而不是用Number。

 

2.選用適當的顯示對象:對於非交互式簡單形狀,請使用 Shape 對象。對於不需要時間軸的交互式對象,請使用 Sprite 對象。對於使用時間軸的動畫,請使用 MovieClip 對象。更多具體情況,參見使用合適的顯示子類

 

3.選擇合適的文本對象:對於只讀文本,最好使用 Flash 文本引擎,它占用較少的內存並提供更好的呈現效果。對於輸入文本,最好使用 TextField 對象,因為在創建典型行為(例如,輸入處理和自動換行)時需要的 ActionScript 代碼較少。

 

4.盡可能使用 Vector 類而不是 Array 類:Vector 類的讀寫訪問速度比 Array 類快。但是Vector內只能存放同一類型的數據,所以我們要根據需求來使用Vector或是Array。在使用Vector時,注意要為矢量分配特定長 度並將其長度設為固定值,因為如果不提前指定矢量的大小,則矢量大小將在矢量用完空間后增加。每次矢量大小增加時,都將分配一個新的內存塊。矢量的當前內 容會復制到新內存塊中。這種額外的分配和復制數據會降低性能。盡可能嘗試使用 Vector 對象 API,因為它們的運行速度可能更快。

 

5.盡可能使用 String 類方法(如indexOf()substr()substring())代替正則表達式來實現基本字符串查找和提取:在使用正則表達式時如果需要對元素進行分組,但不需要在結果中隔離該組的內容,請使用非捕獲組(“(?:xxxx)”)代替正則表達式中的(“(xxxx)”)組。

 

重用對象

盡可能重復使用對象並避免重新創建對象, 因為實例化對象成本很高。而且因為內存分配有時會觸發垃圾回收,所以重用對象還可以減少垃圾回收器運行的機會,從而提高應用程序運行速度。

1.避免在一個循環中創建對象,盡力將對象創建在循環外部並在循環內反復重用它。如下例,我們就重用了BitmapData對象:

// Create a single 20 x 20 pixel bitmap, non-transparent 
var myImage:BitmapData = new BitmapData(20,20,false,0xF0D062); 
var myContainer:Bitmap; 
const MAX_NUM:int = 300; 
  
for (var i:int = 0; i< MAX_NUM; i++) 
{ 
    // Create a container referencing the BitmapData instance 
    myContainer = new Bitmap(myImage); 
  
    // Add it to the display list 
    addChild(myContainer); 
  
    // Place each container 
    myContainer.x = (myContainer.width + 8) * Math.round(i % 20); 
    myContainer.y = (myContainer.height + 8) * int(i / 20); 
}

 

2.使用對象池,在初始化應用程序期間創建一定數量的對象並將其存儲在一個池中,在需要時取用,用完放回池中。

 

釋放內存

在 Flash Player 的發行版中無法直接啟動垃圾回收器,而是被系統自動啟動。想要釋放一個對象,需要通過刪除對象引用的方式進行。Flashplayer debug版本提供了System.gc()接口,我們可以在程序的創作階段利用這個函數來檢驗程序中的對象引用有沒有被正確解除。

要正確的釋放對象,需要注意如下幾點:

1.必須刪除對象所有的引用。

2.對象內部成員必須不存在對外部對象的引用。即刪除所有內部成員的引用。

3.必須刪除EnterFrame,Timer等事件監聽器。對於Timer還必須先stop。

4.對於BitmapData,還需要先用dispose()方法刪除內存中的像素。

5.對於加載的SWF等,需要先用loader.unloadAndStop()卸載。

6.播放完聲音或一個 SoundChannel 實例被用於對聲音執行 stop() 時,就已經已准備好對該聲音進行垃圾回收。

 

關於弱引用

這 種引用不會被垃圾收集器作為判定object是否被回收的依據。它的作用是:如果當一個對象僅僅剩下弱引用時,這個對象將會被垃圾收集器在下一輪回收。但 是弱引用只支持兩種類型:第一種是經常會因為內存管理機制帶來麻煩的事件監聽器,建議每當添加監聽器時,都將其第五個參數選項,即弱引用設置為true。 下面是其對應的參數設置的例子:

    someObj.addEventListener("eventName",listenerFunction,useCapture,priority,weakReference);
    stage.addEventListener(Event.CLICK,handleClick,false,0,true);
    // the reference back to handleClick (and this object) will be weak. 



另一個弱引用支持的是Dictionary object。一般情況下在初始化時設置其第一個參數為true,下面是例子:

    var dict:Dictionary = new Dictionary(true);
    dict[myObj] = myOtherObj;
    // the reference to myObj is weak, the reference to myOtherObj is strong 

 

注意:如果系統認為可用內存不是足夠低,垃圾回收器可能不會運行。垃圾回收的執行時間不可預知。內存分配(而不是對象刪除)會觸發垃圾回收。

關於垃圾回收的詳細講解,可以參看Flash AS3 垃圾回收機制詳解

 

預處理資源和數據

對於一些處理起來較為麻煩的資源和數據,可以進行預處理,以節約CPU資源。

1.避免使用濾鏡,包括經過 Pixel Bender 處理的濾鏡。盡 可能使用通過創作工具(例如 Adobe® Photoshop®)創建的位圖來模擬濾鏡。避免在 ActionScript 中使用運行時創建的動態位圖。使用外部創作的位圖可幫助運行時減少 CPU 或 GPU 負載,特別是當濾鏡屬性不隨時間更改時。如果可能,在創作工具中創建位圖所需的任何效果。然后,可以在運行時中顯示該位圖,而無需對它進行任何處理,這樣 速度要快得多。

 

2.mip 映射:盡量少用 mip 映射。盡管它可以改進縮小位圖的品質,但它對帶寬、內存和速度都有影響。在某些情況下,最好選擇使用通過外部工具預縮放的位圖版本,並將其導入到您的應用程序中。如果只需縮小位圖,不要一開始就使用較大位圖。

 

3.避免復雜矢量圖:使用矢量(而不是位圖)是節省內存的好方法。然而,使用矢量(特別是大量矢量),會顯著增加對 CPU 或 GPU 資源的需求。使用位圖是優化呈現的一個好方法,因為運行時在屏幕上繪制像素比呈現矢量內容需要的處理資源要少。如果矢量圖過於復雜,最好是預處理成位圖。

 

4.使用常量來代替反復重新計算相同的值

 

事件模型

1.用簡單的回調代替事件模型: 使用本機事件模型與使用傳統的回調函數相比,速度更慢且占用的內存更多。必須創建 Event 對象並為其分配內存,而這會降低性能。例如,當偵聽 Event.ENTER_FRAME 事件時,將在各個幀上為事件處理函數創建一個新事件對象。在捕獲和冒泡階段(如果顯示列表很復雜,此成本會很高),顯示對象的性能可能會特別低。

 

2.減少事件處理函數:利用事件捕獲和冒泡可以在一個對象(而不是多個對象)上注冊事件處理函數以提高性能。

 

最大程度減小 CPU 使用量

1.凍結和解凍對象: 要優化您的代碼,請始終凍結和解凍您的對象。凍結和解凍對所有對象都很重要,但對顯示對象尤其重要。即使顯示對象不再位於顯示列表中並正在等待作為垃圾回 收,其代碼仍然占用大量 CPU。例如,它們仍然在使用 Event.ENTER_FRAME。因此,使用Event.REMOVED_FROM_STAGE和Event.ADDED_TO_STAGE事件正確 凍結和解凍對象非常關鍵。

 

2.激活和停用事件:有兩個事件(Event.ACTIVATE和Event.DEACTIVATE) 可以幫助您微調應用程序以使其盡量使用最少的 CPU 周期。這些事件允許您檢測運行時獲得或失去焦點的時間。因此可以對代碼進行優化,以便對上下文更改做出反應。

 

3.禁用鼠標交互: 使用交互式對象(例如 MovieClip 或 Sprite 對象)時,運行時執行本機代碼以檢測和處理鼠標交互。當屏幕上顯示許多交互式對象時,特別是當它們重疊時,檢測鼠標交互可能會占用大量 CPU 資源。避免此處理的一種簡便方法是對不需要任何鼠標交互的對象禁用鼠標交互。可以用mouseEnabled和mouseChildren來禁用鼠標交 互。

 

優化呈現性能

1.減小重繪區域:重繪是Flash Player性能消耗的主要大戶,所以減小重繪區域面積,減少不必要的重繪次數,能減少不必要的性能消耗。可以使用函數 flash.profiler.showRedrawRegions(true);在構建項目時顯示重繪區域以減小重繪區域。要減小重繪區域,主要需要做 到如下幾點:

不要通過將DisplayObject放在后面來隱藏,雖然這樣在界面上看不到了,但是還是會消耗系統資源,應該停止運行隱藏的DisplayObject並將隱藏運行的DisplayObject的visible屬性設置為false或將其從顯示列表中完全刪除。

 

2.在影片品質和效率之間折中。

 

3.避免使用alpha屬性:alpha屬性會帶來不必要的計算,應該避免。

 

4.位圖緩存: 可以利用AS3自帶的cacheAsBitmap屬性來設置緩存,這時,應該將opaqueBackground屬性設置為特定顏色,運行時會將顯示對象 視為不透明,且為DisplayObject設置緩存,而不對容器設置緩存,這樣能最大程度的發揮位圖緩存的作用。另外可以利用BitmapData自己 實現位圖緩存,這樣更能有效的提高性能。

 

5.使用Stage3D: 可以使用Stage3D利用GPU繪圖。

 

優化網絡交互

1.緩存資源:加載資源后將本地緩存,而不是在每次需要時從網絡進行加載。

 

2.使用 Flash Remoting 和 AMF 實現優化的客戶端-服務器數據通信

 

優化循環

1.避免使用for in循環:for in 循環比普通的for循環浪費更多的時間,應該避免。

 

2.采用更快的算法,盡量用Vector或Array的API.

 

3.盡量優化循環內的代碼

有很多蚊子肉,在少量計算時無關緊要,但是在循環中一點的優化說不定也能起到大的作用,這些一點的優化包括:

a.用乘法來代替除法,用位運算代替除2或乘2

b.將多行賦值轉為單行賦值(a=b=c=0)

c.將可以在循環外進行的運算提取到循環外。獲取某些對象的屬性,數組的成員等等都可以算作計算

d.盡可能使用內聯代碼以減少代碼中函數的調用次數。

e.避免使用嵌套的if結構:例如if(a>1&&b>1){}比嵌套的if(a>1){if(b>1){}}要快且代碼清晰。

f.避免使用with語句。

g.用int不用Math.floor():前者比后者快。

h.var obj:Object = new Object()比var obj:Object = {}快。

i.var arr:Array = []比 var arr:Array = new Array()快。

j.if (myObj) 比if (myObj != null) 快。

k.當程序里有多條分支時,將頻繁發生的分支放在上面,如:

if ( conditionmostpopular )  {   

 

}  else if ( conditionSomtimes )   {      

 

}  else   {       // 最少發生

 

}

 

 

參考:http://help.adobe.com/zh_CN/as3/mobile/index.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM