測試使用的 Demo 可以通過 GitHub 下載。
小米 Note3,使用驍龍 660,算是這兩年比較主流的中端芯片,雖然性能在高負荷場景下跟旗艦芯片如驍龍 835 還有一定距離,不過大部分場景下也已經(jīng)夠用。
設(shè)備電量在 60% 以上,處于充足狀態(tài),并使用風扇進行輔助散熱,避免因為電量不足或者過熱導(dǎo)致設(shè)備鎖核降頻,從而引起測試數(shù)據(jù)的波動,無法獲得可以對比的測試結(jié)果。
頁面在 Chrome 上運行在全屏的 WebApp 模式下,如果沒有額外說明,Canvas 的渲染分辨率使用設(shè)備的屏幕分辨率 1080p。
adb shell "dumpsys SurfaceFlinger --latency 'TARGET_WINDOW_NAME'"
使用上述命令可以獲取目標窗口最近 127 幀的更新時間戳,然后用腳本計算出這 127 幀渲染過程中的平均幀率。
另外代碼中也通過計算 JavaScript 中每幀調(diào)用的次數(shù)和時間間隔來計算幀率,然后通過控制臺打印輸出類似下面的信息,實際驗證兩者的結(jié)果基本一致。
WebGL Aqua framerate:1.55fps, program:44, draw call:118
本文的測試數(shù)據(jù)使用第一種方法。
模擬鳥群的運動,包含大量的物理運動計算,實際上是測試 JavaScript 的計算性能。
可以對 numBoids (guimark3.js)參數(shù)進行修改,改變鳥群的數(shù)量,鳥群數(shù)量越大,JavaScript 計算的耗時就越大。
繪制的場景有一定的復(fù)雜度,包含了約 30 個模型,使用了 44 個 Program,當參數(shù)設(shè)定為 500 條魚時,需要調(diào)用 600 多個 Draw Call(不使用 Instance Rendering 的情況下)。
可以配置的參數(shù)如下:
類似雷電的小游戲,多個小位圖的重復(fù)繪制,主要測試 Canvas.drawImage 的性能,跟微信開發(fā)工具自帶的樣例游戲類似。
可以對 enemiesCount(guimark3.js),改變敵機的數(shù)量,從而增加或者減少 drawImage 的調(diào)用次數(shù)。
在 Chrome 渲染流水線里面,Canvas 元素的更新跟其他 DOM 元素的內(nèi)容更新一樣,都需要走非合成器動畫的渲染流水線。而非合成器動畫渲染流水線過于復(fù)雜和冗長,比較小游戲簡單和直接的渲染流水線,會有較多的 Overhead。
不過假設(shè)網(wǎng)頁的運行條件跟小游戲一樣,頁面只有一個 Canvas 元素而不存在其他 DOM 元素,這些 Overhead 其實每個環(huán)節(jié)的耗時都很小,加上 Chrome 多線程高并發(fā)的流水線設(shè)計,實際上大部分開銷都可以忽略不計,對整體性能的影響微乎其微。
WebGL Compute 的測試結(jié)果也驗證了這一點,該 Demo 只有一個 Draw Call,所以我們基本可以忽略繪制部分的影響,JavaScript 計算的開銷也可以認為是基本相同,在小游戲和 Chrome 的性能測試結(jié)果基本一致的情況下,我們可以推斷出渲染流水線本身不會造成明顯的性能差異。
關(guān)于 Chrome 非合成器動畫的渲染流水線可以參考我的文章 - 瀏覽器渲染流水線解析與網(wǎng)頁動畫性能優(yōu)化。
我們把 JavaScript Computing 定義為除了 Native API(2D Canvas,WebGL,etc...)外的其它純 JavaScript 代碼運行的耗時。
小游戲和 Chrome 都使用 v8 虛擬機運行 JavaScript 代碼,理論上 JavaScript 計算的性能不會存在較大差異,些微的差別可能來源自 v8 的版本差異,WebGL Compute 的測試結(jié)果也驗證了這一點。
Chrome 對比小游戲 WebGL 繪制的差別在于:
在 WebGL Aqua 這個 Demo 中,計算部分的開銷很小,大部分是繪制的開銷,Chrome 的多線程模型并沒有帶來多少并發(fā)的優(yōu)勢,只是抵消了 CommandBuffer 機制帶來的一些 Overhead,不過額外的 Render Target 切換和緩存拷貝的影響看起來也很小,Chrome 和小游戲的性能基本持平,甚至 Chrome 還稍微好一些。如果是計算和繪制開銷比較平均的場景,Chrome 可能會有更大的性能優(yōu)勢。
Chrome 對比小游戲 2D Canvas 繪制的差別在于:
因為 Chrome 運行環(huán)境中較高的 per drawImage 的開銷,我們可以在 Canvas Bitmap 測試中看到當 drawImage 的調(diào)用次數(shù)非常高時,Chrome 的 Renderer 線程會被嚴重阻塞而導(dǎo)致幀率下降幅度大大高于小游戲的下降幅度。
WebGL 理論上 Chrome 也會多一些 Overhead,只是 WebGL API 相比 2D Canvas API 的實現(xiàn)要簡單很多,所以這些 Oveahead 實際影響非常小,并沒有 2D Canvas 那么明顯。