(轉)as3效率優化


1、改進算法
無論對於那一種程序,好的算法總是非常重要的,而且能夠極大地提高程序性能,所以任何性能的優化第一步就是從算法或者說程序邏輯的優化開始,檢查自己的程序是否有多余的運算,是否在沒有必要的時候做了無用功,往往從這些方面就能找到那些導致性能低下的地方。

2、優化細節代碼
針對細節總是好的,有一些小技巧比如:
用 var obj:Object = {}; 要比 var obj:Object = new Object();要好;
var arr:Array = []; 要比 var arr:Array = new Array(); 要好;
for (var i:int=0, len=arr.length; i 如果不是為了保存顏色值請不要適用uint這個類型,他的速度比起 int要慢多了;
Array的遍歷要比Object或者Dictionary的枚舉要快得多。
if (myObj != null) 要比 if (myObj) 的速度要快, for (var i:* in myObj) 比 for (var i:String in myObj) 要快;
Dictionary當 weak key設置為 true 的時候要比 false 慢;
var myText:String = “a” + “b” + “c”;
var myText2:String = [ "a", "b", "c" ].join(”");
在JavaScript里面在IE下后者要更快,但是在AS里面,前者更快!
在循環體內聲明變量和在循環體外聲明變量其實速度上不會有太大的區別。

3、權衡程序的結構
程序的架構也非常重要,良好的結構會帶來性能和程序健壯性的提升,但是有的時候又是相互矛盾的,例如代碼寫得過於健壯,反而會影響性能,這個地方需要開發者自己去權衡。

4、小心Flash的重繪
如果你使用的是Flash Player 的Debugger版本,那么請在檢查性能瓶頸的時候不要忘記打開顯示重繪區域的功能,這將幫你迅速定位到舞台上有那些地方被重繪了,找出沒有顯示任何東 西卻不斷重繪的地方,這些地方肯定是有問題的。Flash Player很笨,不會說你把一個DisplayObject的visible設置成false就放棄重繪那個顯示對象。所以請保證你的 MovieClip在visible=false的時候為停止狀態。有一點很有意思,假設兩個現實物體存在 hitTest = true 這樣的關系,那么重繪的區域的面積很有可能 > 兩者的面積總和!

5、以空間換時間
聽起來挺虛,實則很簡單,說白了就是以內存換CPU,例如將不變動的值進行保存,免去下次需要此數據的時候進行再次計算,雖然原理很簡單,但是有的時候卻很容易疏忽掉,而這個往往就造成你的算法效率低下的問題。

6、記得銷毀你的對象
對於非常駐的對象使用完之后記得消除其引用,防止出現內存溢出的問題,往往要做到這一點需要有一個良好的編程習慣。

7、清除冗余的代碼
有些代碼可能你的程序一輩子也不會執行到,請把這些沒有用的代碼或者對象清理掉,否則內存會被偷偷的蠶食掉。

8、小心使用useBitmapCache = true
一般情況下除非你確定這個顯示對象不可能發生變化那么用用也無妨,不過我更推薦自己手動的用BitmapData將該對象Draw一遍,然后讓這個對象徹底消失。否則每次的變動都是巨大的性能消耗。

—————-

前幾日跟小雷配合做了一個項目,訪問量統計的,要處理海量數據(其實萬級別而已)。做出來之后,從程序啟動到畫出來圖形,要超過15秒的腳本執行限 制。這樣肯定是不行的,於是我開始研究程序優化——當然我之前也會有所涉及,只不過沒有系統的總結過,這次需求比較嚴峻,所以整理一下。

flash性能最低的地方依然在於圖形渲染,所以各種循環之中如果可以不包含圖形變化就不要包含。我把圖形變換放到數據運算之后,渲染速度從9秒多降低到0.4秒不到。
循環的速度,有人測出來是for each最快,for其次,while最慢。這個姑且相信吧,因為和我測出來的差不多。
數字類型的效率,int最高,number其次,uint最低。這個和as3剛出現時大家說的,能uint就uint完全不一致,uint甚至無法超過number。所以,循環的時候應該是:
(1)如果要存儲的東西是對象,可以放在一個數組里面進行處理,需要循環的時候,可以用數組方法比如說every;同時,如果存儲的對象包含自己的方法,則可以用for each (var _obj:* in _arr){_obj.method();}這樣的方法。
(2)如果存儲的是普通數據,可以盡量用for(var i:int=0,len:int=_arr.length;i
+=1的效率大於++,也很難理解。
公共屬性,能不用getter/setter方法就不用,直接公開給外部調用修改。當然這種做法很不符合面向對象思想,不過有些時候也可以這么用。
xml的效率並不高,數據存儲簡單格式還是object吧。
剩下的以后補充。

===========================
最近我研究了一些AS3代碼優化的文章,一般都是集中在研究loops 和 Number types上的,本文不在重復類似的測試

下面是我的一些測試結果

Array & Object constructing
構造數組和對象的時候,new Array() and new Object()要比 [] and {}慢3倍的時間

Index Number type for Arrays
數組的數字索引類型

ist[int(0)] 比list[0]要快

Create Array vs. Updating Array
再循環語句中避免多次創建數組,最好創建一次用多次更新內容替換

Nulling Array vs. Splicing Array
對於龐大的數組而言就行splice操作是比較耗成本的,要盡量避免

When working with large Arrays splicing is obviously an expensive operation, you can avoid this by nulling the index and skipping it in a null scenario. If you need to splice in order to keep the Array length low. Then store these nulled indexes in another trash Array once the garbage count has reached a limit you’ve defined loop through the numerically sorted trash indexes deleting splices in bulk. This concept is demonstrated in Tweensy.

Nulling Object vs. Delete Object
delete一個對象的屬性要比把該屬性設置為null 更昂貴,所以對於對象的屬性最好設置為null

Nesting Loops(嵌套循環)
多次嵌套循環效率差,所以最好保證循環在2層以內

Inline code vs. function references
如果在時間幀上的函數很長而且執行時間長,最好,把該函數分成多個小的函數執行。

這樣可以縮短執行時間提高效率

Arguments vs. variable referencing
盡量最小化函數的參數個數

Function apply scoping do it or not?
Scoping function.apply is a little bit slower than not so if you don’t have to then don’t.

Array push vs. Array index
用設置index的方式來代替使用數組函數push

比如

list[list.length] = data; 要比直接用push快600%;

Array emptying – length 0 vs. A new Array
如果你需要設置一個空數組,有一個方便的辦法去選擇,就是通過設置它的length屬性為0

或者你會認為這么做是不錯的選擇,原因是它能節省內存,但是事實上這樣做的執行速度不如直接new array的效率高

當然,如果你需要在一次循環中清除多於510個數組為空時,用length設置為0的時候會更好

Var declarations on multiple lines vs. Var declarations on a single line
將變量聲明在一行中,要比聲明多行更好,效率更高

i.e.
var a:int=0, b:int=0, c:int=0;
vs.
var a:int=0;
var b:int=0;
var c:int=0;

Using Xor to swap variables
如果你想去交換變量,但是又不想創建新的變量的時候,可以用xor

如:

a = a^b;
b = a^b;
a = a^b;

Multiplication vs. Division
乘法的運算速率總是比出發快,比如5000/1000 要比 5000*0.001快130%;

Type casting comparison 強制轉換類型對比
When type casting the keyword as is 250% more efficient than casting by Type(item); Though surprisingly not using either is about 1400% more efficient.

建議使用對應的類型的變量進行比較

同類型的比較效率高的多

Long vs Short variable names
盡量用短的變量名

===================
提高flash程序效率(as3)
提高flash程序效率,這里先舉一個處理字符串的例子,后面轉載其他開發人員的優化經驗,歡迎補充!
———————————————————————————–
action程序員都知道action處理String的效率是非常低的,可是說低的可以,下面代碼可以說明:
var str = “abcde”;
var tmp = “”;
var time1 = getTimer();
for(var i=0;i < 10000;i++){
tmp += str;
}
trace(getTimer() - time1);//1665
將10000個5個字母的字符串連接起來竟然需要1.5s以上的時間(cpu: pm1.4)
而改成10個字母就需要使用4s左右的時間,15個字母就需要5.5s左右的時間
隨着字符串的變長,字符串處理的速度越來越低
那怎么能讓字符串連接的更快呢?看一看下面這段代碼:
time1 = getTimer();
var tmpA = new Array();
for(var i=0;i < 10000;i++){
tmpA[i] = str;
}
var tmp1 = tmpA.join("");
trace(getTimer() - time1);
trace(tmp1 == tmp);
這段代碼是接在上面的代碼后面的,這里思路有所不同的是,在這里先把字符串一個一個的付給數組,然后利用數組的join方面一下子將整個數組轉換為字符 串,你也許會想,先付給數組,然后再有數組轉換,肯定會更慢.但實際上不是這樣的,因為賦值語句在as里面是很快的,所以將10000個字符串付給數組花 不了多長時間,而最后調用的數組的方法是as內部函數,完全由c實現的,因此肯定要比as實現快很多倍,因此整體速度跟上面的代碼就相差很多了,而且隨字 符串增長,效率也不會明顯降低,下面是執行結果:
同樣為10000個字符串連接,5個字符第二種方法只需要140ms,比直接連接字符串快10倍左右,而后面的比較輸出true說明兩個字符串是一樣的
而且當字符串加置10個,15個甚至更多的時候,效率並沒有降低,而仍然用時140ms左右,而當字符串長度達到40的時候,用時才超過了200ms.
-------------------------------下面是較全面的優化-------------------------------
第一章 AS3的一些優化計算方法
用乘法來代替除法(當除數可轉化為有限數的時候)。比如var n:Number = value * 0.5;要比var n:Number = value / 2;快。但差別並不是很大。只有在需要大量計算情況下,比如3D引擎中差別才比較明顯。
用位運算代替除2或乘2。比如10>>1要比10*2快,而10<<1要比10*2快。從測試來看位運算幾乎比乘除快一 倍,但是一般情況下,我們不能選擇位運算,比如我們就不能用13>>1來代替13/2,盡管前者比后者運算速度更快,但2者的運算結果卻不一 樣。所以還是要看具體情況。
用unit()或int()代替取整運算Math.floor()和Math.ceil()。比如var test:uint = uint(1.5);要比var test:Number = Math.floor(1.5);快;而var test:uint = uint(1.5)+1;要比var test:Number = Math.ceil(1.5);也快。如果是Math.floor(),還可以用位運算(>>0)來代替。比如var test:uint =1.5>>0,比unit()或int()更快。
用乘-1來代替Math.abs()方法。比如var nn:Number = -23;var test:Number= nn < 0 ? nn * -1 : nn;要比var nn:Number = -23;var test:Number = Math.abs(nn);快。當然還有更多的優化計算的方法。一般來說,低級運算要比高級運算速度;內部方法比調用其他方法速度快。另外要注意的是,這 些方法有的時候可能並一定適用。
第二章 Actionscript 優化指南
原著 Marco Lapi,alias Lapo, aw譯
在這篇文章中,我們將討論多種優化 Actionscript 代碼的方法.此外我們也針對一些典型的游戲代碼進行了系列測試,來最大限度的發掘、提高Flash播放器的性能。何時進行優化對現有程序進行優化的過程, 有時十分的冗長與困難,這與原始代碼的非優化程度有關,所以在投入大量時間進行代碼優化之前,最重要的是要估計出要在什么地方對代碼做出修改或替換。
一個游戲代碼的最重要的部分就是主循環體,通常情況下該循環體要在flash的每一幀上執行,並控制游戲中的角色屬性和重要的數據參數。而對於主循環體以外的部分,也可能是次要循環部分,同樣要注意是給其否分配了過多的資源,而沒有分配給那些更需要資源的核心部分。
通過積累在各處節約出來的時間(可能每處僅僅是幾個毫秒),您會明顯發現自己的swf運行得更加穩定,並且游戲感也大大加強。
簡潔與高效的代碼
書寫出十分簡潔、可以再次調用的代碼(有時可能是面向對象的)是一項精細的工作,但這需要多年的編程經驗。對於OOP(object oriented programming,面向對象的程序設計),有些場合根本利用不到它的優勢,這使得它顯得十分奢侈。在有限的資源條件下(可能是flash播放器的原 因),通過更先進的方法,像剛剛提到的OOP,就可能反而導致令人不滿意的結果。
我們並不是說OOP對游戲編程不好,只是在某些場合它顯得過於奢侈和多余。畢竟有時候“傳統的方法”卻能得到更好的結果。大體而言,用OOP是比較 好的,因為它讓代碼維護更加簡單。但在后文中,你會看到有時為了充分發揮flashplayer性能,而不采用OOP技術。例如:處理快速滾動或者計算十 分復雜的數學問題。基本的優化一提及代碼優化,我們馬上會聯想到執行速度的改進,而很少去考慮系統資源的分配。這是因為當今,即使是將被淘汰的計算機,都 有足夠的內存來運行我們大部分的flash游戲(128M的內存足以滿足大多數情況的需要,況且,512M的內存是當今新電腦的基本配置)
變量
在各種重要的代碼優化手段中,有這么一條:在定義局部變量的時候,一定要用關鍵字var來定義,因為在Flash播放器中,局部變量的運行速度更快,而且在他們的作用域外是不耗占系統資源的。
aw附:var變量僅僅在花括號對中才有“生命”,個人認為沒有系統學過編程的人容易出錯的一個地方:
awMC.onLoad = function(){
var aw = 1;
}
awMC.onEnterFrame = function(){
//不存在aw這個變量
}
一段非優化代碼:
function doSomething()
{
mx = 100
my = 100
arr = new Array()

for (y=0; y < my; y++)
{
for (x=0; x < mx; x++)
{
i = (y * mx) + x
arr[i] = i
}
}
return arr
}
這段代碼中,並未聲明函數體內的那些變量(那些僅僅在函數內使用的變量)為局部變量,這使得這些變量被播放器調用的速度更慢,並且在函數執行完畢的時候仍然耗占系統資源。
下面列出的是經過改進的同樣功能的代碼:
function doSomething()
{
var mx = 100
var my = 100
var arr = new Array()

for (var y=0; y < my; y++)
{
for (var x=0; x < mx; x++)
{
var i = (y * mx) + x
arr[i] = i
}
}
return arr
}
這樣一來所有的變量均被定義為了局部變量,他們能夠更快地被播放器調用。這一點在函數大量(10,000次)循環運行時顯得尤為重要!當一個函數調用結束的時候,相應的局部變量都會被銷毀,並且釋放出他們占有的系統資源。
*********************************************************************************************************************************
onEnterFrame 事件
onEnterFrame事件對於游戲開發者而言是非常有用的,它使得我們能夠快速、反復地按照預設幀頻(fps)運行一段程序。回想在 Flash5的時代,這(onEnterFrame實時監控)是一種非常流行的技術,用這樣的事件來控制機器游戲對手的邏輯,又或者我們可以在每一個子彈 上設置這樣的事件來監測子彈的碰撞。
實際上,我們並不推薦給過多的MoveClip添加這樣的事件,因為這樣做會導致“無頭緒碼(spaghetti code)”的出現,並且容易導致程序效率明顯降低。
大多數情況下,用單獨一個onEnterFrame事件就可以解決問題了:用這一個主循環來執行你所需要的操作。
另一個簡單的辦法是設置一個合適的幀頻:要知道幀頻越高,CPU資源就越緊張。在幀頻為25-35(fps)之間時,onEnterFrame足以很好地執行較復雜代碼,哪怕你的計算機配置較低。因此,在沒有特殊要求的場合,我們不推薦使用高於60(fps)的幀頻。
矢量圖與位圖
在處理圖形前,我們一定要做出正確的選擇。Flash能對矢量圖和位圖進行完美的兼容,然而矢量圖和位圖在播放器中的表現實質卻完全不同。在用到矢 量圖的時候,我們要盡可能簡化它們的形狀,去除多余的端點。這樣做將大大降低播放器用於呈現矢量圖所要進行的計算量。另一個重要方面在於線條的運用,盡量 減少和避免冗陳的線條結構,因為它們會直接影響到flash的播放效率。
當某個實例透明度小於100時,也會對播放速率造成影響,所以如果你發現自己的Flash播放速率過慢,就去挑出這些透明的實例來吧!
那么,如果真的需要呈現比較復雜的場景時,你就最好考慮使用位圖實現。雖然Flash在對位圖的渲染效率上並不是最優越的(比如和Flash的“兄 長”Director比起來),但豐富的視覺內容呈現只能靠位圖(與位圖同復雜度的矢量圖形渲染速率非常低)了,這也是很多基於區塊的游戲中廣泛采用像素 圖作為背景的原因。順便要提到的是,Flash雖然對GIF,JPG和PNG都有所支持,但是渲染速度上PNG還是占有絕對優勢,所
以我們建議flash中的位圖都盡可能采用PNG格式。
影片剪輯(MovieClip)的可視性[下面將MovieClip簡稱為mc]
您可能會經常碰到這樣一種情況:有大量不可見/屏幕外的mc等待出場(比如游戲中屏幕外的地圖、人物等等)。
要知道,播放器仍然要消耗一定的資源來處理這些不可見/屏幕外的mc,哪怕他們是單幀,非播放的狀態。
最好的解決辦法之一是給這些mc一個空白幀,當他們不出現在屏幕上時,你能用gotoAndStop()語句跳轉到這一幀,從而減少播放器對資源的需求。
請務必記住,這種情況下,簡單的設置可見度屬性為不可見( _visible = false )是無效的,播放器將繼續按照這些mc所停留或播放的幀的復雜度來分配資源。
數組
數組在各種需要記錄數據的應用程序和游戲中都被廣泛的使用。
一個典型的例子就是基於區塊的Flash游戲,在這樣一類的游戲中,地圖有時被存放成形如arr[y][x]的二維數組。雖然這是一種很常見的方 法,但是如果用一維數組的話,卻能提高程序的運行效率。另一個重要的方法來提高數組效率是在數組遍歷的時候使用for in 循環來代替傳統的 for 或者while循環語法。
例如:
一段代碼如下
for (var i in arr)
{
if (arr[i] > 50)
{
// 進行某些操作
}
}
它的執行速度明顯高於這一段代碼:
for (var i=0; i < 10000; i++)
{
if (arr[i] > 50)
{
// 進行某些操作
}
}
前者的效率比后者提高了30%,這個數字在你的游戲要逐幀執行這一段代碼的時候顯得更加寶貴!
=================
第一章 AS3的一些優化計算方法
1.用乘法來代替除法(當除數可轉化為有限數的時候)。比如var n:Number = value * 0.5;要比var n:Number = value / 2;快。但差別並不是很大。只有在需要大量計算情況下,比如3D引擎中差別才比較明顯。

2.用位運算代替除2或乘2。比如10>>1要比10*2快,而10<<1要比10*2快。從測試來看位運算幾乎比乘除快 一倍,但是一般情況下,我們不能選擇位運算,比如我們就不能用13>>1來代替13/2,盡管前者比后者運算速度更快,但2者的運算結果卻不 一樣。所以還是要看具體情況。

3.用unit()或int()代替取整運算Math.floor()和Math.ceil()。比如var test:uint = uint(1.5);要比var test:Number = Math.floor(1.5);快;而var test:uint = uint(1.5)+1;要比var test:Number = Math.ceil(1.5);也快。如果是Math.floor(),還可以用位運算(>>0)來代替。比如var test:uint =1.5>>0,比unit()或int()更快。

4.用乘-1來代替Math.abs()方法。比如var nn:Number = -23;var test:Number= nn < 0 ? nn * -1 : nn;要比var nn:Number = -23;var test:Number = Math.abs(nn);快。當然還有更多的優化計算的方法。一般來說,低級運算要比高級運算速度;內部方法比調用其他方法速度快。另外要注意的是,這 些方法有的時候可能並一定適用。

第二章 Actionscript 優化指南
原著 Marco Lapi,alias Lapo, aw譯

在這篇文章中,我們將討論多種優化 Actionscript 代碼的方法.此外我們也針對一些典型的游戲代碼進行了系列測試,來最大限度的發掘、提高Flash播放器的性能。何時進行優化對現有程序進行優化的過程, 有時十分的冗長與困難,這與原始代碼的非優化程度有關,所以在投入大量時間進行代碼優化之前,最重要的是要估計出要在什么地方對代碼做出修改或替換。

一個游戲代碼的最重要的部分就是主循環體,通常情況下該循環體要在flash的每一幀上執行,並控制游戲中的角色屬性和重要的數據參數。而對於主循環體以外的部分,也可能是次要循環部分,同樣要注意是給其否分配了過多的資源,而沒有分配給那些更需要資源的核心部分。
通過積累在各處節約出來的時間(可能每處僅僅是幾個毫秒),您會明顯發現自己的swf運行得更加穩定,並且游戲感也大大加強。

簡潔與高效的代碼

書寫出十分簡潔、可以再次調用的代碼(有時可能是面向對象的)是一項精細的工作,但這需要多年的編程經驗。對於OOP(object oriented programming,面向對象的程序設計),有些場合根本利用不到它的優勢,這使得它顯得十分奢侈。在有限的資源條件下(可能是flash播放器的原 因),通過更先進的方法,像剛剛提到的OOP,就可能反而導致令人不滿意的結果。

我們並不是說OOP對游戲編程不好,只是在某些場合它顯得過於奢侈和多余。畢竟有時候“傳統的方法”卻能得到更好的結果。大體而言,用OOP是比較 好的,因為它讓代碼維護更加簡單。但在后文中,你會看到有時為了充分發揮flashplayer性能,而不采用OOP技術。例如:處理快速滾動或者計算十 分復雜的數學問題。基本的優化一提及代碼優化,我們馬上會聯想到執行速度的改進,而很少去考慮系統資源的分配。這是因為當今,即使是將被淘汰的計算機,都 有足夠的內存來運行我們大部分的flash游戲(128M的內存足以滿足大多數情況的需要,況且,512M的內存是當今新電腦的基本配置)

變量

在各種重要的代碼優化手段中,有這么一條:在定義局部變量的時候,一定要用關鍵字var來定義,因為在Flash播放器中,局部變量的運行速度更快,而且在他們的作用域外是不耗占系統資源的。

aw附:var變量僅僅在花括號對中才有“生命”,個人認為沒有系統學過編程的人容易出錯的一個地方:復制內容到剪貼板代碼:
awMC.onLoad = function(){
var aw = 1;
}
awMC.onEnterFrame = function(){
//不存在aw這個變量
}
一段非優化代碼:
function doSomething()
{
mx = 100
my = 100
ar = new Array()

for (y=0; y < my; y++)
{
for (x=0; x < mx; x++)
{
i = (y * mx) + x
arr[i] = i
}
}
return arr
}這段代碼中,並未聲明函數體內的那些變量(那些僅僅在函數內使用的變量)為局部變量,這使得這些變量被播放器調用的速度更慢,並且在函數執行完畢的時候仍然耗占系統資源。

下面列出的是經過改進的同樣功能的代碼:復制內容到剪貼板代碼:
function doSomething()
{
var mx = 100
var my = 100
var ar = new Array()

for (var y=0; y < my; y++)
{
for (var x=0; x < mx; x++) { var i = (y * mx) + x arr[i] = i } } return arr }這樣一來所有的變量均被定義為了局部變量,他們能夠更快地被播放器調用。這一點在函數大量(10,000次)循環運行時顯得尤為重要!當一個函數調用結 束的時候,相應的局部變量都會被銷毀,並且釋放出他們占有的系統資源。 onEnterFrame 事件 onEnterFrame事件對於游戲開發者而言是非常有用的,它使得我們能夠快速、反復地按照預設幀頻(fps)運行一段程序。回想在Flash5的時 代,這(onEnterFrame實時監控)是一種非常流行的技術,用這樣的事件來控制機器游戲對手的邏輯,又或者我們可以在每一個子彈上設置這樣的事件 來監測子彈的碰撞。 實際上,我們並不推薦給過多的MoveClip添加這樣的事件,因為這樣做會導致“無頭緒碼(spaghetti code)”的出現,並且容易導致程序效率明顯降低。 大多數情況下,用單獨一個onEnterFrame事件就可以解決問題了:用這一個主循環來執行你所需要的操作。 另一個簡單的辦法是設置一個合適的幀頻:要知道幀頻越高,CPU資源就越緊張。在幀頻為25-35(fps)之間時,onEnterFrame足以很好地 執行較復雜代碼,哪怕你的計算機配置較低。因此,在沒有特殊要求的場合,我們不推薦使用高於60(fps)的幀頻。 矢量圖與位圖 在處理圖形前,我們一定要做出正確的選擇。Flash能對矢量圖和位圖進行完美的兼容,然而矢量圖和位圖在播放器中的表現實質卻完全不同。在用到矢量圖的 時候,我們要盡可能簡化它們的形狀,去除多余的端點。這樣做將大大降低播放器用於呈現矢量圖所要進行的計算量。另一個重要方面在於線條的運用,盡量減少和 避免冗陳的線條結構,因為它們會直接影響到flash的播放效率。 當某個實例透明度小於100時,也會對播放速率造成影響,所以如果你發現自己的Flash播放速率過慢,就去挑出這些透明的實例來吧! 那么,如果真的需要呈現比較復雜的場景時,你就最好考慮使用位圖實現。雖然Flash在對位圖的渲染效率上並不是最優越的(比如和Flash的“兄 長”Director比起來),但豐富的視覺內容呈現只能靠位圖(與位圖同復雜度的矢量圖形渲染速率非常低)了,這也是很多基於區塊的游戲中廣泛采用像素 圖作為背景的原因。順便要提到的是,Flash雖然對GIF,JPG和PNG都有所支持,但是渲染速度上PNG還是占有絕對優勢,所 以我們建議flash中的位圖都盡可能采用PNG格式。 影片剪輯(MovieClip)的可視性[下面將MovieClip簡稱為mc] 您可能會經常碰到這樣一種情況:有大量不可見/屏幕外的mc等待出場(比如游戲中屏幕外的地圖、人物等等)。 要知道,播放器仍然要消耗一定的資源來處理這些不可見/屏幕外的mc,哪怕他們是單幀,非播放的狀態。 最好的解決辦法之一是給這些mc一個空白幀,當他們不出現在屏幕上時,你能用gotoAndStop()語句跳轉到這一幀,從而減少播放器對資源的需求。 請務必記住,這種情況下,簡單的設置可見度屬性為不可見( _visible = false )是無效的,播放器將繼續按照這些mc所停留或播放的幀的復雜度來分配資源。 數組 數組在各種需要記錄數據的應用程序和游戲中都被廣泛的使用。 一個典型的例子就是基於區塊的Flash游戲,在這樣一類的游戲中,地圖有時被存放成形如arr[y][x]的二維數組。雖然這是一種很常見的方法,但是 如果用一維數組的話,卻能提高程序的運行效率。另一個重要的方法來提高數組效率是在數組遍歷的時候使用for in 循環來代替傳統的 for 或者while循環語法。 例如: 一段代碼如下復制內容到剪貼板代碼: for (var i in arr) { if (arr[i] > 50)
{
// 進行某些操作
}
}它的執行速度明顯高於這一段代碼:復制內容到剪貼板代碼:
for (var i=0; i < 10000; i++) { if (arr[i] > 50)
{
// 進行某些操作
}
}前者的效率比后者提高了30%,這個數字在你的游戲要逐幀執行這一段代碼的時候顯得更加寶貴!

高級優化:

1) for循環 和 while循環
用while循環將會得到比for循環更好的效率。然而,從數組中讀取數據,用for in循環式最好的選擇!

所以我們不推薦使用:復制內容到剪貼板代碼:
for (var i=0; i < 1000; i++)
{
//進行某些操作
}而推薦使用
var i=-1
while (++i < 1000)
{
//進行某些操作
}2) 從數組中讀取數據
我們通過測試發現,for in循環的效率大大高於其他的循環方式。參看:復制內容到剪貼板代碼:
arr = []
MAX = 5000
//數組賦值
for (i=0; i < MAX; i++)
{
arr[i] = i
}
var item = null
// For 循環
for (var i=0; i < MAX; i++)
{
item = arr[i]
}
// For 循環
for (var i in arr)
{
item = arr[i]
}
// While 循環
i = -1
while(++i < MAX)
{
item = arr[i]
}3) 向數組中寫入數據(while , for)可以看到while循環稍占優勢。

4) _global(全局)變量同Timeline(時間軸)變量
我們猜測采用全局變量能提高變量調用速度,然而效果並不像預計的那樣明顯。

5) 單行、多行變量賦值
我們發現單行變量賦值效率大大高於多行。比如:
a = 0
b = 0
c = 0
d = 100
e = 100

效率就不如:
a = b = c = 0
d = e = 100

6) 變量名尋址
這個測試反映了變量名的預尋址是非常重要的,尤其是在循環的時候,一定要先給丁一個指向。這樣大大節約了尋址時間。

比如:復制內容到剪貼板代碼:
var num = null
t = getTimer()
for (var i=0; i < MAX; i++)
{
num = Math.floor(MAX) – Math.ceil(MAX)
}
t1.text = “Always lookup: ” + (getTimer() – t)就不如:復制內容到剪貼板代碼:
t = getTimer()
var floor = Math.floor
var ceil = Math.ceil
for (var i=0; i < MAX; i++)
{
num = floor(MAX) – ceil(MAX)
}7) 短變量名和長變量名
變量名越短,效率越高。考慮到長變量名也有它的好處(比如,便於維護等),因此建議在關鍵部位(比如大量循環出現的時候)使用短變量名,最好就1-2個字符。

循環前、后聲明變量
在測試前,我們認為循環前聲明變量會更加節約時間,不料測試結果並不明顯,甚至還恰恰相反!復制內容到剪貼板代碼:
// 內部聲明
t = getTimer()
for (var i=0; i < MAX; i++)
{
var test1 = i
}
t1.text = “Inside:” + (getTimer() – t)
// 外部聲明
t = getTimer()
var test2
for (var i=0; i < MAX; i++) { test2 = i }9) 使用嵌套的if結構 當用到復雜的條件表達式時。把他們打散成為嵌套的獨立判斷結構是最佳方案。下面的代碼我們進行了測試,發現這種效果改進明顯!復制內容到剪貼板代碼: MAX = 20000 a = 1 b = 2 c = -3 d = 4 var i=MAX while(–i > -1)
{
if (a == 1 && b == 2 && c == 3 && d == 4)
{
var k = d * c * b * a
}
}
//下面的判斷更加節省時間
var i=MAX
while(–i > -1)
{
if (a == 1)
{
if (b == 2)
{
if (c == 3)
{
if (d == 4)
{
var k = d * c * b * a
}
}
}
}
}10) 尋找局部變量(this方法同with方法比較)
局部變量的定位方法很多。我們發現用with比用this更加有優勢!復制內容到剪貼板代碼:
obj = {}
obj.a = 1
obj.b = 2
obj.c = 3
obj.d = 4
obj.e = 5
obj.f = 6
obj.g = 7
obj.h = 8
obj.test1 = useThis
obj.test2 = useWith
MAX = 10000
function useThis()
{
var i = MAX
while(–i > -1)
{
this.a = 1
this.b = 2
this.c = 3
this.d = 4
this.e = 5
this.f = 6
this.g = 7
this.h = 8
}
}
function useWith()
{
var i = MAX
while(–i > -1)
{
with(this)
{
a = 1
b = 2
c = 3
d = 4
e = 5
f = 6
g = 7
h = 8
}
}
}11) 循環監聽鍵盤事件
同剛才所提到的尋址一樣,我們實現給一個指向會得到更好的效率,比如:
keyDown = Key.isDown
keyLeft = Key.LEFT

//我們再用 if (keyDown(keyLeft))
附:我們測試了按鍵代碼和鍵值常量的效率發現並無太大差別。

12) Math.floor()方法與int()
這個問題曾在Flashkit的論壇被提出討論過。測試表明,舊的int方法反而效率更高。我們的測試結果也反映了這一點。

13)eval表達式與中括號語法
我們並沒有發現明顯的差別,並不像剛才所述那樣,舊的eval表達式比起中括號方法並沒有太大的優勢
var mc = eval(”_root.myMc” + i)
var mc = _root["myMc" + i]
//兩者效率差不多16) 涉及MC的循環:ASBroadcaster 同歡同循環的差別

結論

我們從這些測試結果中發現,對於不同的需求,采用不同的代碼,我們可以大大提高腳本的執行效率。雖然我們在這里羅列了許多的優化代碼的方法,需要大家自己測試、實驗的還有很多(考慮到每個人的需求不同).如果你想更加深入地討論這類問題。可以來我們的論壇。

aw附:
終於翻譯完了,自己也學到很多好東西,大家又什么問題可以去gotoAndPlay的官方,也可以來我的Blog提出!

第三章 黑羽AS心得:淺釋ActionScript的代碼優化
本機函數要比用戶定義的函數運行速度更快。本機函數即Flash中內有的一些函數(intrinsic),比如hitTest(),你沒必要自己寫一個類似的。

3.不要過多使用 Object 類型。
數據類型注釋應力求精確,這樣可以提高性能。只有在沒有適當的備選數據類型時,才使用 Object 類型。同時也便於代碼管理,時刻知道對象的類型和作用。同時也有利於編譯器編譯時優化。

4.避免使用 eval() 函數或數據訪問運算符。
通常,較為可取且更有效的做法是只設置一次局部引用。不得已時才用eval,比如轉換_droptarget為MovieClip時。

5.在開始循環前將 Array.length 賦予變量,尤其是大的循環。
在開始循環前將 Array.length 賦予變量(比如var iLength:Number),將其作為條件使用,而不是使用myArr.length 本身。
原因,在循環中,iLength是Number變量,會被放入寄存器使用,效率遠比訪問Array再得到length高。例如,應使用復制內容到剪貼板代碼:
var fontArr:Array = TextField.getFontList();
var arrayLen:Number = fontArr.length;
for (var i:Number = 0; i < arrayLen; i++) {
trace(fontArr[i]);
}來代替:復制內容到剪貼板代碼:
var fontArr:Array = TextField.getFontList();
for (var i:Number = 0; i < fontArr.length; i++) {
trace(fontArr[i]);
}6.注重優化循環及所有重復動作。
Flash Player 花費許多時間來處理循環(如使用 setInterval() 函數的循環)。

7.在局部變量夠用時,不要使用全局變量。類靜態變量也要少用。
全局變量是開發者的惡夢。實在需要全局變量的話,我建議使用singleton設計模式來進行管理。

8.聲明變量時,添加 var 關鍵字。
這是為了編譯時讓編譯器知道你的變量類型,優化編譯。

黑羽補充一點:對關鍵字的使用要謹慎。
不贊成使用關鍵字作為自己的method和屬性名,除非你確認后續開發不會用到相同的事件名和屬性名。
但你怎么知道flash使用了多少隱藏關鍵字?太多了!比如說 className, invalidate, refresh, mouseOver等等不常用的關鍵詞。好的方法是使用SEPY編輯器來寫代碼,那里面加亮了所有公布的和沒有公布的關鍵詞。而且因為很有可能和 start,load,等這些常用的事件名重復,帶來代碼不必要的修改和麻煩。

9.對涉及到調用繪圖資源的函數時,盡量先多判斷再調用。
所有漸變,位置變化,創建刪除MC,組件等函數都涉及到繪圖資源的調用。在很多情況下,盡量先用邏輯判斷變量或者對象的屬性,必要時再調用這些函數。這樣可以節省較多的計算資源。

 

------------------------------------------------------------------------------------------------------------------------------------------------------------

 


免責聲明!

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



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