Udacity 瀏覽器渲染優化
Udacity上的 bowser render optimization課程,透過chrome dev tool的timeline來debug,試著將瀏覽器的渲染速度達到60fps。
Frame
如果要在瀏覽透過60fps的速度去渲染畫面
也就是說我們必須在1000ms/60frame ~ 16ms
16毫秒以內將要渲染在畫面上的設定都處理完成
而實際上大約是只有10~12ms
Render Tree
瀏覽器先向server發出http request
接者會收到server傳來的html,css檔案
透過解讀html裡面的tag去建立DOM tree
再來透過css file, inline style, 3rd party css lib去建立CSS tree
並將兩者合併變成Render Tree
Render Tree 就不包含html裡面的head tag
也不會有任何script
另外若Css有對Dom Tree的元素作一些操作
例如
|
|
在確定每個元素的規則樣式之後
接著就是計算每個DOM元素最終在銀幕上的大小和位置
也就是Layout(佈局)
再來就是Paint,將文字、顏色或者圖形等等的繪製在多個不同的圖層上
並透過最後的Composite來做合併
簡化成下圖來做表示整個渲染階段的動作
因此在做60fps優化的時候
我們可以透過chrome dev tool提供的timeline去看這些渲染階段所佔用的時間
另外csstriggers提供了csstrigger的查詢
在做畫面優化的時候可以了解到哪些操作所產生的步驟比較少
進而去提高畫面的表現
App lifecycle
在做優化之前我們應該要先知道
我們有哪些時間上的限制
和使用者對於一個Web app的期待和反應
Action | Times | Description |
---|---|---|
R(Response) | 100ms | 使用者和網頁做互動時的反饋時間 |
A(Animate) | 16ms (actual 10~12ms) | 我們期望的60fps的網頁效能 |
I(Idle) | 50ms | 使用者看到畫面並且稍微瀏覽的時間 |
L(Load) | 1000ms | 使用者送出request到畫面出現的時間 |
在了解到App lifecycle之後
我們就可以針對下面的流程來做優化拉!
Optimizing JS
Optimizing JS for Animations
不要去做 Micro-optimization
像是去比較for-loop跟while-loop的差別
可以透過timeline tool
看到哪個function導致執行時間變長
Web Wokers
有時候我們會透過javascript去處理一些運算較為久的task
並在算完之後渲染到畫面上
但由於js engine是單執行緒
在處理這些task的時候可能會導致渲染的效能變慢
這時候就可以透過web worker建立一個背景的執行緒
幫我們完成這些work
透過這段code來宣告一個新的web worker
|
|
接著我們就可以在worker.js裡面去處理我們要執行的task
main script和web worker主要透過 postMessage() 方法以及 onmessage 事件處理器來溝通
要注意的是在worker.js中必須用self來指定全域物件
因為此時的worker不是在window這個scope底下
|
|
透過worker處理完的data我們就可以在main script當中透過onmessage來監聽
|
|
如此一來就可以把較為耗資源的運算跟渲染的運算做分離
避免渲染時卡卡的情形發生了
JS Memory Management
- Writing Fast, Memory-Efficient JavaScript on Smashing Magazine
- Memory Management on MDN
- High-Performance, Garbage-Collector-Friendly Code on Build New Games
Optimizing Style & Layout Calculation
Style change的cost是和change的element數量成線性的關係
因此我們會希望每次做style change的時候改變的element數量越少越好
藉此加快 Style Caluculation的速度
Selector Matching
Block Element Modifier
再透過class改變style的時候
我們會希望影響到的element越少越好
並且在selector的地方越簡單越好
Stopping F(orced) S(ynchronous) L(ayout) Strategy
千萬不要改變渲染的順序否則會造成很差的perf
JS -> Style -> Layout -> Paint -> Composite
Optimizing Paint & Composite Calculation
Paint Profiler
透過timeline的Paint
去記錄整個paint的過程
甚至可以直接看到在對應的function call時
所完成的paint
Composite
越多Layer Composite time越久
所以當我們透過增加Layer去減少Paint次數時
Composite的時間就會變長
Manage Layers
|
|
可以讓有will-change或transform的component
建立自己的Layer
試著把.box加上will-change: transform
渲染效果差超級多
Layers Counting
透過Timeline的Paint Profiler
我們可以直接點擊Layers看到頁面有多少層Layer
並且可以透過圖像化的表示將Layer做旋轉
看到不同Layers的相對位置