The pixel pipeline
ブラウザがHTMLをレンダリングする際に何を行っているか
The pixel pipeline
ブラウザがレンダリングをする際に行っていることは、大きく分けると次の5つになる:
- JavaScript: DOM操作で画面の見た目を変更にかかわるスクリプトの処理。
- Style: 要素に対してどのCSSルールが適用されているかを計算するプロセス。
.class1や.class2のように複数CSSセレクタが該当するものは、CSS適用の優先度から最終的にあてはまるルールを決定する。 - Layout: 位置, 幅, 高さなど、要素がスクリーンのどのスペースを占めるかを決定するプロセス。Firefoxでは
reflowと呼ばれる。width,height,left,topを変更するとLayout処理が発生する。 - Paint: 描画処理呼び出しリストの作成と要素ピクセルに色で埋める処理(ラスタライズ)を行う。
テキスト、色、画像、ボーダー、影を描画する処理を含む。
color,background-colorやborder-radius,border,box-shadowなどを変更するとPaintの処理が発生する。 - Composite: ブラウザは複数のレイヤ(*1)と呼ばれる単位で描画されている。ページ全体にレイヤが正しい順序で描画を行うプロセス。
transform,opacityの変更はこのプロセスのみを発生させる。
再描画の際に実行されるプロセスが少ないほど高速となるので、アニメーションやスクロールなどの高負荷処理の部分では Compositeのみを発生させるようチューニングするのが望ましい。
Side Navigationでパフォーマンス比較
Side Navigationをアニメーションで表示させてパフォーマンスの違いを確認する
使用するHTML
<div class="app"> <div class="side-menu">side-menu</div> <div class="header"> <button class="menu-button">open</button> </div> </div>1. leftプロパティでアニメーション
.side-menu { left: -102%; transition: left 150ms linear;}
.side-menu--open { left: -70%; transition: left 150ms linear;}2. transformプロパティでアニメーション
will-changeプロパティでレイヤーを生成している。(非対応ブラウザにはtransform: translateZ(0);)
.side-menu { transform: translateX(-102%); transition: transform 300ms linear; will-change: transform;}
.side-menu--open { transform: translateX(-30%); transition: transform 300ms linear;}比較結果
-
leftプロパティでアニメーション
-
transformプロパティでアニメーション
大幅な差は確認できなかったが、transformプロパティでのアニメーションのほうがFPSが安定していることがわかった。
今回は調査しなかったがwill-changeプロパティはGPUメモリにレイヤを格納し続けるのでスマートフォンなどでは電池消費が大きくなるそうで、
アニメーション直前にwill-changeをオンにするのが良い方法らしい。
*1 レイヤー: GPUで処理される領域。GPUへテクスチャとしてアップロードされる。1つのレイヤが大きい場合はより小さいタイルという単位でアップロードされる。
参考
- Rendering Performance
- Smooth as Butter: Achieving 60 FPS Animations with CSS3
- CSS Triggers どのCSSルールがどのプロセスを発生させるか
- Chrome Developer Toolsを使いこなそう!
- DevToolsのTimelineパネルを見ながら、レンダリングの仕組みを理解する
- Accelerated Rendering in Chrome Chromeのレイヤー概念とGPUについて