顯示具有 效能 標籤的文章。 顯示所有文章
顯示具有 效能 標籤的文章。 顯示所有文章

2014年5月16日 星期五

[AS][starling] Starling 的性能優化


主要是要記錄這篇文章

http://wiki.starling-framework.org/manual/performance_optimization

 加上一些心得!

starling 相關的的優化是不是 有用 我沒有試過 !

不過裡面寫的 AS 的優化 很多是有用的

像是迴圈的 幾個部分 我都測試過 都有幫助 !

不過主要也是要記錄這篇文章!!!

2014年3月11日 星期二

[AS3][效能] 處理 重繪區域比顯示區域大的一些方法 IV

這一篇主要是因為我看了 blitting 這種做法後

想對我自己的方式做改善所進行的一些測試

首先資料來源如下

1.bitmapdata 的功能測試 

2.利用 blitting 改善 movieclip 的效能(使用 Scout)


我自己測的結果如下

各 30 回ループ

draw :: 3 ms
最低速に比べて約 12500 %高速

copyPixels :: 3 ms
最低速に比べて約 12500 %高速

fillRect :: 6 ms
最低速に比べて約 6250 %高速

clone :: 61 ms
最低速に比べて約 614 %高速

new :: 102 ms
最低速に比べて約 367 %高速

merge :: 105 ms
最低速に比べて約 357 %高速

setPixel :: 225 ms
最低速に比べて約 166 %高速

setVector :: 375 ms
最低速に比べて約 100 %高速

clickで再計算

當然這個僅供參考

因為實際的部分 絕對不如 那個範例所顯示的

但是我自己看重的重點是!

單就 draw 和 copyPixels 的處理速度上!

以這個例子是同一個級別的,

所以就我自己的方法 特別改用 copyPixels  去做!(單對bitmapdata 的部分)

反而會影響效能!

更多的問題會是像下面的 blog 講的

利用 blitting 改善 movieclip 的效能(使用 Scout)

所講的.... 濾鏡 更新大小 等等的東西

那篇文章中的例子會很快 而且快的那樣明顯的原因是~

他只畫一份 然後給其他的使用! 而且是一次貼上一個區塊!

而且 bitmapdata 的更新只更新他畫的那一塊!

並不需要重新的 一塊一塊畫濾鏡的部分

所以越多 理論上是越明顯!

然而在我的 其他三篇中 寫的方式 並沒有辦法使用這個方法來做優化!

如果要做到的加速方式!

我必須去判斷哪一塊有更新 然後就更 新的部分一塊貼圖

就會有優化的效果!

但是就我自己的測試 不明顯!

所以相關的報告就不放上來了

話說這一篇也卡了兩個多月了 orz

2012年8月29日 星期三

[AS3] 處理 重繪區域比顯示區域大的一些方法 III

這個是 同事 給我的外國得相關的資料

http://www.flashxpress.net/ressources-flash/dopez-votre-framerate-avec-les-classes-animatedbitmap-et-animatedbitmapdata/

http://www.bytearray.org/?p=117

基本上這種做法 叫 香蕉片 ( Banana Slice)

因為香蕉片的 原始碼 我沒找到(所以下面講的香蕉片都是指第一個網址)

不過基本理念(作法)應該和我的做法是一樣的

利用 draw 去繪製 MC 成 bitmapdata

用來取代一些複雜而且多特效(濾鏡.遮罩 大小改變..等等) 的 MC

相關的應該不用介紹了~~ 不過還是簡單的複習一下

先講我看過 第一個網址的東西後 我的是如何改良

香蕉片板
1. 是分成兩段 一段是將MC 產生對應影格數的 bitmapdata

2. 在利用另外一組去將它顯示到場景上

他的做法和我的做法在某種程度上 不謀而合

都會把定時呼叫的東西 拆出來 可以另外的設定

在經過了這樣久之後 再次看到類似作法的人

終於有不孤單的感覺...

不過我發現他有一些繪圖是在做白工!

不過也許是因為他預先一格內畫好全部的關係

所以必須再多繪一次元件上的濾鏡

就我自己的測試 但是不管是程式加的  還是原本元件上有的

只要用 draw 畫下來 基本上都包含了該元件的濾鏡效果

不會有效果的目前發現的有

blendMode

角度 大小

除了 blendMode 相關的處理 都可以參考第一個的 CODE

不過我自己是很猶豫一點!因為是對應 MC 上的角度 和 scale 的屬性!

說不定有一些操作還是會用到

這樣會被 這個 吃掉 可能會造成一些問題!!

我自己得會將原本的 MC 留著 (因為要留著一直去 draw)

所以一些屬性改變的問題 還是會找到原本的 MC 上!

但是香蕉片版卻不會!! 這一點使用上要小心

blendMode 在FLASH 提供的函數就能解決

但問題是 你要將一個 bitmapdata分成超多小區塊~~去處理~

而且大小 形狀 等等的都必須 設定的精準一點才可能

所以這部分是說真的十分得麻煩

目前我沒有好的處理方式! 而且香蕉片的也不處理這一塊

所以我就....先跳過


再來說說效能的部分

我的版本每回合去 draw  大約 800 * 600 左右的大小的 bitmapdata 在  FPS 是 24

CPU 都是在 14~20 左右

但是使用香蕉片的方式 大約是 5~7 左右的 CPU 消耗!!

這樣關鍵的差距 就是在每一格都畫 和 是用已經存好的bitmapdata 間的差距

因為他的 CPU 消耗真得很省 所以我也弄了一個 我的 香蕉片 以下我都簡稱我的香蕉片

唯一作的改良是 原本一格將全部的 MC 畫出 bitmapdata 的部分

改成 每一格都畫 直到全部影格都畫好為止 就會跳去 純粹使用 bitmapdata

而且 整個是 static 的!!! 共用一個主體 一個計時器 !!!

好講幾個關鍵的重點!!

1. 存 bitmapdata 的部分 記得使用 clone 小小的卡了一下

2. 存幾張 bitmapdata 的部分 最好可以手動設定!! 不要自動抓 MC 的影格長度

3. 不要將全部的圖片合成一張 這樣會浪費相當多的 記憶體.....

分開來會比較好一點 不過這個也是要看情況

先就第三點 說一下

本來我有一個設定 可以把在一起的 MC 一起畫

本來每格畫 這個事情就很簡單 也沒問題

但是變成要使用預先畫好的 bitmapdata 時 變成要計算 一起畫的影格的最小公倍數!!

而且存圖區域變成 兩個區域的聯集區域

這一塊一整個麻煩~ 以我遇到的情況 100格對 170格....

原始MC板 記憶體約 36mb

使用香蕉片板 約 19x

使用我的香蕉片板 瞬間突破 270 我就果斷停止了

所以還是分開存會比較省  這個是我最近使用上遇到的情況

我又把那個一起畫的功能拿掉了......

話說這個功能多災多難 我前前後後 大概拿掉了三四次了

2012年7月10日 星期二

[AS3] 處理 重繪區域比顯示區域大的一些方法



我想有處理過一些閃光字的人一定會發現這個問題
就是閃光字明明很小
但是他的重繪範圍比較大
想看這個比較好的效果的可以到 閃光字 這看
如果有 DEBUG版的 player 的話可以開啟 重繪範圍看看

我來介紹一下我知道解決這個問題的幾個方法!

1.
從結構面去解決
只要有作移動補間動畫是在 遮罩的圖層上的
不是被遮圖層上 如下圖



那最簡單的解法
就是 把整個遮罩物件(遮罩 和 被遮的物件 一整組設成 快取點陣圖)
如下圖

那這樣他的補間動畫就會是
不過有得時候
因為某些複雜的表現
沒辦法把 補間動畫作在 遮罩區
那下一種程式面的方法就可以解決

2.
使用 mc.scrollRect 屬性
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/DisplayObject.html#scrollRect

不過在我的測試下 好像是沒用的....

也許這個也有一些 我不知道的限制....
但是在另外的測試 下是有用的
效果會和你 限制的區域一樣大!
不過這邊我沒去深究! 就把它當成是一種解法

我有測到一個限制~
就是這個物件 要設 快取成點陣圖 後才有用
以我這個範例來說 也是設了就有用了
沒設 就會和這個圖一樣

不過可能 還有一些其他的因素 例如 player 的版本 等等的
總之...我覺得第三個方法 我比較喜歡 所以我也沒深究了

3.
最後這個是一個簡單的想法
利用 顯示物件沒有貼在場景上
但是依然存在 而且可以被繪圖這一點!
然後 重繪的區域就會是你繪圖的區域

下面是這個簡單的想法的 CODE
有興趣的可以看一下

package
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.MovieClip;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.geom.Rectangle;
 
    import ui.logo;
 
    public class MovieClipToBitmapDemo extends Sprite
    {
     
        private var _mc:MovieClip;
        private var _bmd:BitmapData;
        private var _bm:Bitmap;
        private var _rect:Rectangle;
     
        public function MovieClipToBitmapDemo()
        {
            _mc = new logo();
            this.addEventListener(Event.ENTER_FRAME, onEnterFrameFun);
            _rect = new Rectangle(0,0,109,78);
            _bmd = new BitmapData(109, 78, true, 0);
            _bm = new Bitmap();
            _bm.smoothing = true;
         
            this.addChild(_bm);
            draw();
        }
     
        private function onEnterFrameFun(e:Event):void
        {
            draw();
        }
     
        private function draw():void
        {
            _bmd.fillRect(_rect, 0);
            _bmd.draw(_mc,null,null,null,_rect,true);
            _bm.bitmapData = _bmd;
        }
    }
}


希望可以幫到一些人
然後再補充一點
就是如果這個被重繪的圖
裡面有很複雜
而且 有多重的濾鏡 遮罩 互相影響!
那重繪這個動作
可以幫你節省一些效能
但是 記憶體就會略多了 !

2012年3月28日 星期三

[AS3] 取得FUNCTION 的名稱

其實我只是在想一個可以偷懶得好方法~
這樣在 LOG檔可以不用寫太多東西~

來簡介一下~
目前我會的取得FUNCTION NAME的名稱的方法


public function getFunctionName(f:Function, root:*):String
{
var t:Object = root;
var methods:XMLList = describeType(t)..method.@name;
for each (var m:String in methods)
if (t.hasOwnProperty(m) && t[m] != null && t[m] === f) return m;          
return null;
}
而且還要配合
trace(getFunctionName(arguments.callee, this));

這樣子來使用!
非常麻煩 而且還有限定 是公開 非靜態的方法

雖然很早就在 Ticore 大的BLOG 上拜見過這招
不過我都一直沒想到可以拿來應用!

直到我看到某個範例

public static function getName():String {
var error:Error = new Error();
var stackTrace:String = error.getStackTrace();     // entire stack trace
if(stackTrace == null) return 'null';
var startIndex:int = stackTrace.indexOf("at ", stackTrace.indexOf("at ") + 1); //start of second line
var endIndex:int = stackTrace.indexOf("()", startIndex);   // end of function name
var lastLine:String = stackTrace.substring(startIndex + 3, endIndex);
var functionSeperatorIndex:int = lastLine.indexOf('/');
var functionName:String = lastLine.substring(functionSeperatorIndex + 1, lastLine.length);
return functionName;
}

這招 BUG 到逆天了
不管是靜態 公開 私用 等等的FUNCTION
通通都可以抓的到
更扯的是可以抓到上一層 上上一層
雖然還是有使用限制!
在非 debug 或是 ADL的環境下無法使用!
因為 getStackTrace 會是 null
不過跟原來的那招比~
好用很多了

更扯的是!


getFunctionName函數執行1000次 消耗的時間為2057毫秒
getName函數執行1000次 消耗的時間為45毫秒
不過直接輸出字串 約 1毫秒....

這兩個執行時間的差距!
如果你是跟我一樣的偷懶開發者!
在LOG的部分 不要忘了這招! 而且在非 debug的播放器下自動失效!

下面是我測的是文件

public function testLocalClassCall()
{
unitTestTool.addFunction('test02', this);
unitTestTool.addFunction('test03', this);
unitTestTool.addFunction('test04', this);
unitTestTool.startFunTest(1000);
unitTestTool.start();
}

public function test02():void
{
var s:String = getFunctionName(arguments.callee, this);
}

public function test03():void
{
var s:String = getName();
}

public function test04():void
{
var s:String = 'test04';
}

下面是他的輸出!(每次輸出都有差!)

[SWF] C:\FlexWorks\testLocalClassCall\bin-debug\testLocalClassCall.swf - 6,432 bytes after decompression
test02函數執行1000次 消耗的時間為1843毫秒
test03函數執行1000次 消耗的時間為43毫秒
test04函數執行1000次 消耗的時間為1毫秒
[Unload SWF] C:\FlexWorks\testLocalClassCall\bin-debug\testLocalClassCall.swf

2012年3月8日 星期四

[AS3] 調教效能問題:濾鏡 並不會比較耗資源!

一樣也是在公司遇到的一個小狀況
讓我 非常非常的訝異~

多層濾鏡所構成的元件在 the miner 監測下所耗用記憶體
和 一張 PNG 所構成的元件 是一樣的!

本來我推論 可能會在 CPU 的耗用上有差異
但是更嚇的人是~
沒有~兩個我自己在測的時候都是 10% 左右~
圖中所見的差異...
那應該抓圖時間的錯置的問題...

大家可以自己回去測看看~




這個是我自己弄得一個小測試~~
個人懷疑多層濾鏡的元件
自動的轉成類似 bitmapdata的方式(我沒勾點陣快取 也沒設定)
而不是和以前一樣試即時運算的結果~
所以比較不吃資源和記憶體!


所以期待靠把濾鏡去掉 去增進效能的部分
最好還想想就好~
就我目前
做的一些部分來分享一下心得



1. 
把滑鼠事件關閉 能省的資源不多 
特別是物件不多的情況下  
層次不多 或是 根本沒監聽的情況下
關閉 是省不了太多資源的!

甚至如果你是一層一層一個一個元件關 那消耗的資源還會比較多 !
以我自己的例子 一個mc 物件下面有 200~300個 sprite原件~
你沒關 所消耗的資源量 在沒監聽的情況下
基本上 和只關 最上面 mc 元件是一樣的
如果你跟我一樣傻傻的從最裡面的 SP 元件開始關起!
那恭喜 你還會消耗更多的資源

但是我用很多 我自己覺得蠻 BUG的寫法~
利用事件流的部分~所以關閉對我自己的案子來說
是有作用的

2.
把濾鏡 換成 圖片(就這篇文章專為這點寫的)
說真的用處真的不大~
不過換成圖 還是會有一點點的縮減的
特別是你用換的圖會比較小 而且重複利用的時候
個人懷疑 他是把每個元件都快取成 點陣圖
但是每個點陣圖 是獨立存在記憶體中的!
所以換成同一個元件! 會有一點點的幫助!

3.
減少使用 movieClip 真的會節省很多資源!
特別是內有複雜原件的 mc 拆成多個 簡單的 sprite 在某種程度上
是非常有用處的
個人在這個部分 節省了相當 相當多的記憶體
第一點提到的 mc 原來內部都是用 mc 去包!
但是我只是將 底層類別改成 sprite
整體來說 減少了 20~30 mb的記憶體的資源
比我換了 400~500張左右的圖
所節省的 20mb 左右還來的多.

4.
大圖換小圖 有用!
多張靜態合成一張 有用!

5.
剩下的就是一些
縮減無用的程式碼
物件變數清空
固定不用的變數改成常數
減少使用一些過度的變數

6.
還有 到MC 的最後一格
如果你用程式讓他回到第一格!
在某些情況下 不會構成 物件 消失在建造的情況
如果你沒下 那這個物件會在更新一次
雖然不知道這部分 會影響多少~
但介意的人 就多一個CODE巴

7.
其實 timer 或是 setTimeout 等的東西
吃記憶體也是蠻凶的~個人懷疑 某開場爆增的 20mb
就是因為這個部分
不過這部分我自己是還夾了 事件發送..
等等等的東西在~
所以也不太確定!

有再考慮把這部分換成 enterFrame 去監聽 !
看看會不會比較省一點~
雖然我覺得不會~不過至少就某種程度來說
好控制~
比寫在元件最後一個影格送出EVENT 或是 seTimeout 的部分都好控制多了

雖然這幾點 感覺用處不大!
但是還是有一點點的用處~
有類似問題的可以考慮試看看

以我手上的案子~
最一開始沒調整過
開場約是 144~150 mb左右的記憶體
經過我自己一堆調整後
開場約 118 ~124
不過 穩定後 大約都是  106~118 左右的記憶體!

如果以關閉全部動畫和元件中的事件流...
穩定的時候 大約可以壓到 89mb左右....(最佳情況)

不過遊戲中 有一個算是特殊遊戲的東西~
這部分很誇張~
載入就約 220左右~
效能最高可以吃到 699mb

經過我一些調整後 大約最高 650mb
不過開場始終壓不下來~慘的是還會飆的比沒調高....
讓我自己覺得非常的失敗~
而且還是將大圖換小圖後的結果!

不過穩定約 186 mb 都是差不多的! 調前調後都一樣
不過我已經將大量 可以換成 靜態圖 取代的 濾鏡效果都替換了
連 大量的 大圖我都 換成小圖了....

這邊我想除了我從 程式的部分去調外~
原件的部分 我真的不知道怎樣調了...