本文說明如何使用 DevTools 找出瀏覽器繪製階段的瓶頸,並結合 GPU 與合成層(Compositing Layer)的機制優化動畫效能。

建構視角的對應章節:瀏覽器渲染流程

概覽#

當動畫出現效能問題時,光看 Performance 面板上一長條的綠色繪製區塊很難定位真正原因。通常會搭配 DevTools 的其他面板觀察繪製過程與 layer 資訊,主要工具有三個:

  • Paint Profiler:呈現繪製(Paint)階段中所有步驟的細節與時間軸。
  • Layers tool:列出所有 layer 並把它們在頁面中視覺化呈現。
  • Rendering tab:直接在頁面標出 layer 邊界與重繪區塊。

工具介紹#

Paint Profiler#

使用前要先在 Performance 面板的設定中開啟 Enable advanced paint instrumentation,這樣繪製過程中每一步才會被紀錄。錄製後點擊 Paint 區塊,下方會多出 Paint Profiler 分頁,內容由三部分組成:

  • 整段繪製流程的時間軸
  • 每一道繪製指令
  • 每個時間點的繪製結果

時間軸上柱體長度代表花費時間,可以拖選一小段檢視該段內的指令與當下結果。指令列中常見如 drawTextBlob 用於繪製文字,展開後可以看到座標、顏色等屬性,也會出現 saverestoretranslate 這類常見於 Canvas 的指令。

Layers Tool#

從 More tools 進入 Layers 面板,左側列出頁面所有 layer,點擊任一個(或在中央視覺化區直接選取)就能看到大小、產生原因、記憶體用量等細節。上方工具列可以切換顯示模式,畫面太亂時可以關掉 Paints 選項只留 layer 邊界。

Frames#

開啟 Enable advanced paint instrumentation 後,點擊 Frames 中任一幀也會看到 Layers 分頁,介面與 Layers 面板一致,適合觀察特定一幀的 layer,且能避開動畫太多時 Layers 面板卡住的狀況。

Rendering Tab#

按下 ESC 展開 Drawer,於選單中找到 Rendering tab。與繪製最相關的兩個選項:

  • Paint flashing
  • Layer borders

Paint flashing#

把頁面中正在重繪的區域以綠色框標出,框越多越大代表繪製成本越高。如果某個內容幾乎沒變化卻不斷被重繪,就值得考慮把它獨立成自己的 layer。

Layer borders#

不只看哪裡被重繪,還能標示 layer 邊界。被獨立出來的 layer 會以橘色框線標示,藍綠色框線則代表 tile —— 一個 layer 會被切成多個 tile 以加速繪製,切割方式由瀏覽器決定。

實際範例#

開啟示範頁面後會看到滿滿的方塊,按下 Animate 讓方塊轉圈時頁面明顯卡頓;切換到 Isolate 後動畫立刻變得流暢。

把剛剛介紹的工具拿來檢查就能找到原因。

Performance#

未獨立 layer 時 FPS 平均只有 20,下方有一大串綠色繪製區塊,GPU 幾乎沒在休息;獨立 layer 後 FPS 幾乎穩定在 60。

Layers Tool#

未獨立時只看到一片大的 layer,獨立後每個方塊都長出自己的 layer。

Paint flashing 與 Layer borders#

未獨立的版本會看到整個畫面瘋狂重繪,獨立後幾乎沒有重繪事件;layer borders 也清楚顯示橘色框已經圈住每個方塊。

解釋#

原本範例用 transform: translate(); 讓方塊轉圈,按 Isolate 後改成 transform: translate3d();(與 transform: translateZ(); 同效),會把元素獨立成新的 layer。原本要一直重繪整個畫面,變成只是移動 layer 再合成,幾乎不需要重新繪製。

加上 will-change: transform; 也能達到同樣的效果,把元素提升到新的合成層。

原文出處#

  • 原書/iThome:https://ithelp.ithome.com.tw/articles/10249933