はじめに
ブラウザの仕組みなどに関心がある方なら、Chrome の GPU アクセラレーションによるレンダラ / コンポジット オペレーションについて詳しく説明した素晴らしい記事が最近公開されたことをご存じでしょう。まず、Chrome での高速レンダリング: レイヤモデルでは、Chrome がレイヤのコンセプトを使用してページを描画する方法について詳しく説明しています。また、Chrome での GPU 高速コンポジットでは、Chrome がこれらのレイヤを GPU とともに使用してページをレンダリングする方法について詳しく説明しています。
哲学的な質問
3D 用のソフトウェア ラスタライザの作成に多くの時間を費やした結果、ページの描画時に一部の CSS プロパティのパフォーマンスが変化することが明らかになりました。たとえば、小さな画像を画面にラスタライズする処理は、任意の形状にドロップ シャドウを描画する処理とはまったく異なるアルゴリズムのオペレーションです。そこで、さまざまな CSS プロパティがページのレンダリング負荷にどのように影響するかという疑問が生じました。
私の目標は、CSS のプロパティと値の大きなセットをペイント時間で分類し、どのタイプの CSS プロパティが他のプロパティよりもパフォーマンスが高いかを把握することでした。そこで、CSS のペイント時間を数値で可視化するために、ダクトテープとバブルガムを使って自動化を記述しました。これは次のように機能しました。
- 個別の HTML ページのスイートを生成します。各ページには、1 つの DOM 要素と、それに付加された CSS プロパティのいくつかの組み合わせが含まれます。
- 各ページで次の処理を行う自動化スクリプトを実行します。
- Chromeを起動
- ページを読み込む
- ページの Skia Picture を生成する
- Skia ベンチマークで取得した各 Skia 画像を実行して、タイミングを取得します。
- すべてのタイミングをダンプして、数字を確認します。(この部分は重要です…)
この設定では、一連の HTML ページが生成されます。各ページには、CSS プロパティと値の一意の組み合わせが含まれています。たとえば、次の 2 つの HTML ファイルがあります。
<style>
#example1 {
background: url(foo.png) top left / 50% 60%;
padding: 20px;
margin-top: 10px;
margin-right: 20px;
text-align: center;
}
</style>
<div id="example1">WOAH</div>
もう 1 つは、より複雑な
<style>
#example1 {
background-color:#eee;
box-shadow: 1px 2px 3px 4px black;
border-radius: 50%;
background: radial-gradient(circle closest-corner, white, black);
padding: 20px;
margin-top: 10px;
margin-right: 20px;
text-align: center;
}
</style>
<div id="example1">WOAH</div>
以下は、最後の例のバリエーションで、radial-gradient 値のみを変更しています。
<style>
#example1
{
background-color:#eee;
box-shadow: 1px 2px 3px 4px black;
border-radius: 50%;
background: radial-gradient(farthest-side, white, black);
padding: 20px;
margin-top: 10px;
margin-right: 20px;
text-align: center;
}
</style>
<div id="example1" style="padding: 20px; margin-top: 10px;margin-right: 20px; text-align: center;">WOAH</div>
各ページは、Chrome の新しいインスタンスに読み込まれます(ページのリロード時に古い状態によってタイミングが偏らないようにするため)。そして、Skia Picture(*.SKP)が取得され、ページの描画に使用される Skia コマンドが評価されます。各 HTML ファイルの SKP ファイルが生成されると、別のバッチを実行して、*.SKP ファイルを Skia Benchmark アプリケーション(Skia ソースコードからビルド)にプッシュします。このアプリケーションは、そのページのレンダリングにかかった平均時間を出力します。
データの評価
これにより、一連の CSS プロパティの描画にかかる時間を大まかにグラフ化できるようになりました。むしろ、CSS プロパティをペイント パフォーマンスでスタック ランキングできるようになります。以下は、Chrome 27 ベータ版で取得した大きなグラフで、このプロセスから得られたタイミング データの完全なセットを示しています。Chrome は時間の経過とともに高速化されるため、すべてのデータは変更される可能性があります。
各垂直バーは、CSS プロパティの 1 つの組み合わせを持つページの描画時間を表します(100 倍に拡大。このグラフの真のスケール値は 0、1.56 ミリ秒)。きれいな線がたくさんありますが、この形式ではあまり役に立ちません。有用な傾向を見つけるには、データ マイニングを行う必要があります。
まず、一部の CSS プロパティは、他のプロパティよりもレンダリングのコストが高いことがわかります。たとえば、DOM 要素にドロップ シャドウを描画するには、スプラインなどの複雑な処理を伴うマルチパス オペレーションが必要になります。一方、不透明度のレンダリングは比較的簡単です。
2 つ目は、より興味深い点ですが、CSS プロパティの組み合わせによって、それぞれのプロパティのペイント時間の合計よりもペイント時間が長くなる可能性があるということです。観察者の視点から見ると、これは少し奇妙です。A+B = C であり、2.2C ではないと予想されます。たとえば、box-shadow と border-radius-stroke を追加します。
ここで特に興味深いのは、box-shadow プロパティ自体ではなく、特定の値の組み合わせです。たとえば、以下は box-shadow : 50% と border-radius のグループ化と値のバリエーションを示しています。
データを見ると、この状態がしばらく続いています。さまざまな奇妙な組み合わせがあり、私のテストスイートではそのすべてを網羅できていません。興味深い結果をもたらす可能性のあるテストや組み合わせは、まだたくさんあります。
ページのレンダリング ウェイトを確認する
ページ上の各要素のレンダリング時間を追跡できるようになったことで、デベロッパーはページ レンダリングの負荷と、それがサイトの応答性にどのように影響するかを評価できるようになりました。ここでは、そのためのヒントをいくつか紹介します。
- Chrome デベロッパー ツールの Continuous Paint モードを使用して、どの CSS プロパティにコストがかかっているかを把握します。
- CSS のレビューを既存のコードレビュー プロセスに組み込んで、パフォーマンスの問題を検出する CSS の中で、グラデーションやシャドウなど、負荷が高いことがわかっているものを使用している箇所を探します。「これらは本当にここに必要か?」と自問してください。
- 判断に迷う場合は、常にパフォーマンスの向上を優先してください。ユーザーは、列のパディング幅がどれくらいだったかは覚えていなくても、サイトを訪れたときの印象は覚えているものです。
最後に
このテストで最も興味深いことの一つは、Chrome のバージョンごとにタイミングが変化し続けることです(高速化が期待されます)。ブラウザ ソフトウェアは常に変化する領域です。今日遅くても、明日には速くなる可能性があります。この記事から、すでに border-radius:5 を持つ要素に box-shadow: 1px 2px 3px 4px を配置しないようにする方法を学ぶことができます。しかし、より重要なのは、CSS プロパティがページの描画時間に直接影響するという点です。