はじめに
ブラウザの仕組みなどについて最新情報を常に把握している方なら、Chrome の GPU アクセラレーションによるレンダラ/合成オペレーションについて最近発表された素晴らしい記事があることをご存じでしょう。まず、Chrome での高速レンダリング: レイヤモデルでは、Chrome がレイヤのコンセプトを使用してページを描画する方法について説明しています。さらに詳しくは、Chrome での GPU アクセラレーション コンポジットで、Chrome が GPU とともにこれらのレイヤを使用してページをレンダリングする方法について説明しています。
哲学的な質問
3D 用にソフトウェア ラスタライザの作成に多くの時間を費やした結果、ページの描画時に一部の CSS プロパティのパフォーマンスが異なることが明らかになりました。たとえば、小さな画像を画面にラスタライズすることは、任意の形状にドロップシャドウを描画することとはまったく異なるアルゴリズム操作です。そこで、さまざまな CSS プロパティがページのレンダリング重みにどのように影響するかという疑問が生まれました。
私の目標は、大量の CSS プロパティ/値をペイント時間別に分類し、他の CSS プロパティよりもパフォーマンスが高いタイプの CSS プロパティを把握することでした。そのため、ダクトテープとチューインガムで自動化を記述し、CSS ペイント時間に数値の可視性を追加しようとしました。その仕組みは次のとおりです。
- 個々の HTML ページのスイートを生成します。各ページには、1 つの DOM 要素と、それに関連付けられた CSS プロパティの組み合わせが含まれています。
- 各ページに対して次の処理を行う自動化スクリプトを実行します。
- Chromeを起動
- ページを読み込む
- ページの Skia Picture を生成する
- 撮影した各 Skia Picture を Skia Benchmark で実行してタイミングを取得します。
- すべてのタイミングをダンプして、数字に驚嘆します。(この部分は重要です)
この設定では、一連の 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>
以下の例は、前回の例のバリエーションで、放射状グラデーションの値のみを変更しています。
<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 ベンチマーク アプリケーション(Skia ソースコードからビルド)に push します。このアプリケーションは、そのページのレンダリングに要した平均時間をダンプします。
データの評価
これにより、CSS プロパティのセットによるペイントにかかる時間を大まかに把握できるようになりました。つまり、ペイント パフォーマンスに基づいて CSS プロパティをランク付けできるようになります。Chrome 27 ベータ版で取得した大きなグラフを以下に示します。このグラフには、このプロセスのタイミング データがすべて含まれています。なお、Chrome は日々高速化しているため、すべてのデータは変更される可能性があります。
各縦棒は、CSS プロパティの 1 つの組み合わせを使用したページのペイント時間を表します(100 倍に拡大。このグラフの真のスケール値は 0、1.56 ms です)。きれいな線がたくさんありますが、この形式ではあまり役に立ちません。有用な傾向を見つけるには、データ マイニングを行う必要があります。
まず、一部の CSS プロパティは他のプロパティよりもレンダリングにコストがかかることがわかります。たとえば、DOM 要素にドロップシャドウを描画するには、スプラインなどの厄介な要素を含むマルチパス オペレーションが必要になりますが、不透明度の場合はレンダリングが容易です。
2 つ目は、より興味深い点です。CSS プロパティを組み合わせると、それぞれの合計よりもペイント時間が長くなることがあります。観察者の視点から見ると、これは少し奇妙です。A+B = 2.2C ではなく、A+B = C と予想されます。たとえば、box-shadow
と border-radius-stroke
を追加します。
興味深いのは、box-shadow
プロパティ自体ではなく、その特定の値の組み合わせが検出されることです。たとえば、次の図は、値が異なる box-shadow : 50%
と border-radius
のグループ化を示しています。
データを見ると、この状態がしばらく続いています。さまざまな奇妙な組み合わせが多数あり、私のテストスイートではほとんどテストされていません。興味深い結果が得られるテストや組み合わせがまだたくさんあります
ページのレンダリング重量を確認する
ページ上の各要素のレンダリング時間をトラッキングできるため、デベロッパーはページのレンダリング重みと、それがサイトの応答性に与える影響を評価できます。開始するためのヒントをいくつかご紹介します。
- Chrome DevTools の Chrome の連続ペイント モードを使用して、どの CSS プロパティがコストに影響しているかを把握します。
- 既存のコードレビュー プロセスに CSS レビューを組み込んで、パフォーマンスの問題を検出します。グラデーションやシャドウなど、コストが高いと知られているものを CSS で使用している箇所を探します。本当に必要なものかどうかを自問します。
- 不明な点がある場合は、常にパフォーマンスを重視してください。ユーザーは列の余白幅を覚えていないかもしれませんが、サイトの使い心地は覚えています。
まとめ
このテストで最も興味深いのは、タイミングが Chrome のバージョンごとに変更されることです(速くなることを願っています)。ブラウザ ソフトウェアは絶えず変化するサーフェス領域です。今日遅いコンテンツが、明日は速くなる可能性があります。この記事から得られる教訓は、border-radius:5
がすでに存在する要素に box-shadow: 1px 2px 3px 4px
を配置しないことです。ただし、より有益な情報は、CSS プロパティがページのペイント時間に直接影響するという点です。