CSS の描画時間とページ レンダリングの重み

はじめに

ブラウザの仕組みなどについてよくご存じかと思いますが、最近では、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 ファイルが生成されたら、別のバッチを実行して、Skia Benchmark アプリケーション(Skia ソースコードから構築)を通じて *.SKP ファイルを push します。このアプリケーションは、そのページのレンダリングにかかった平均時間をダンプします。

データの評価

これにより、CSS プロパティのスイートがペイントに要する時間を大まかに把握できるようになりました。つまり、ペイント パフォーマンスに基づいて CSS プロパティをランク付けできるようになります。次の大きなグラフは Chrome 27 ベータ版で、このプロセスによるすべてのタイミング データを示しています。なお、Chrome は日々高速化しているため、すべてのデータは変更される可能性があります。

テスト内のすべての組み合わせのタイミング

各縦棒は、CSS プロパティの 1 つの組み合わせを使用したページのペイント時間を表します(100 倍に拡大。このグラフの真のスケール値は 0、1.56 ms です)。きれいな線がたくさんありますが、この形式ではあまり役に立ちません。有用な傾向を見つけるには、データ マイニングを行う必要があります。

まず、一部の CSS プロパティは他のプロパティよりもレンダリングにコストがかかることがわかります。たとえば、DOM 要素にドロップシャドウを描画するには、スプラインなどの厄介な要素を含むマルチパス オペレーションが必要になりますが、不透明度の場合はレンダリングが簡単です。

CSS プロパティが 1 つしかない要素の描画にかかる時間

次に、さらに興味深いことに、CSS プロパティの組み合わせは、各要素の合計よりもペイント時間が長くなる場合があります。観察者の視点から見ると、これは少し奇妙です。A+B = 2.2C ではなく、A+B = C と予想されます。たとえば、box-shadowborder-radius-stroke を追加します。

テストのすべての並べ替えのタイミング

興味深いのは、box-shadow プロパティ自体ではなく、その特定の値の組み合わせが検出されることです。たとえば、次の図は、値が異なる box-shadow : 50%border-radius のグループ化を示しています。

テスト内のすべての組み合わせのタイミング

データを見ると、この状態がしばらく続いています。さまざまな奇妙な組み合わせが多数あり、私のテストスイートではほとんどテストされていません。興味深い結果が得られるテストや組み合わせがまだたくさんあります

ページのレンダリング重量を確認する

ページ上の各要素のレンダリング時間をトラッキングできるため、デベロッパーはページのレンダリング重みと、それがサイトの応答性に与える影響を評価できます。開始するためのヒントをいくつかご紹介します。

  1. Chrome DevTools の Chrome の連続ペイント モードを使用して、どの CSS プロパティがコストに影響しているかを把握します。
  2. CSS レビューを既存のコードレビュー プロセスに組み込んで、パフォーマンスの問題を検出します。 グラデーションやシャドウなど、高コストであることがわかっているものを CSS 内で使用している場所を探します。本当に必要なものかどうかを自問します。
  3. 不明な点がある場合は、常にパフォーマンスを重視してください。ユーザーは列の余白幅を覚えていないかもしれませんが、サイトの使い心地は覚えています。

まとめ

このテストで最も興味深いのは、タイミングが Chrome のバージョンごとに変更されることです(速くなることを願っています)。ブラウザ ソフトウェアは絶えず変化するサーフェス領域です。今日遅いコンテンツが、明日は速くなる可能性があります。この記事では、すでに border-radius:5 を含む要素に box-shadow: 1px 2px 3px 4px を配置しないようにする方法について説明します。しかし、より重要なポイントは、CSS プロパティがページのペイント時間に直接影響を与えるということです。

参照