Catchpointを使ったWebページのパフォーマンス計測

技術部開発基盤グループの外村です。最近はクックパッドのレシピサービスのWebフロントエンドの改善に取り組んでいます。その一環でWebサイトのページロードのパフォーマンス計測をおこなっているので、今回はその取り組みについて紹介します。

Webページのパフォーマンスといっても、文脈によってそれが指すものは様々です。サーバーのレスポンスタイムのみを指すこともあれば、ブラウザがページをレンダリングするまでの時間を指すこともあります。また、レンダリング後にUIの操作やアニメーションがどのぐらいの速度で動くかというのもWebページのパフォーマンスの1つです。今回はブラウザでWebサイトを開いてからページが表示されるまでのパフォーマンス(ページロードのパフォーマンス)にフォーカスします。

継続的なパフォーマンスの計測

ページロードのパフォーマンスを計測する手法はいくつかあります。まず、簡単なのは Google Chrome の DevTools に付属している Lighthouse を使う方法です。DevTools の Audits タブを選択して計測をおこなうと、次のように詳細なパフォーマンスレポートを見ることができます。

f:id:hokaccha:20181129161257p:plain

DevTools を使った計測は便利なのですが、単発の計測では意図せずパフォーマンスが劣化したときに気づけませんし、マシンのスペックによって数値がばらけてしまうこともあります。パフォーマンス改善のための計測は、同一の環境から自動で定期的に計測することが重要です。

ページロードのパフォーマンスを自動で測定するツールはWebPagetestSpeedCurveNew Relic Syntheticsなど様々なものがあります。クックパッドでは、以前以下の記事でも紹介した、Catchpointというサービスを利用しています。

Synthetic Monitoring を活用したグローバルサービスのネットワークレイテンシの測定と改善 - クックパッド開発者ブログ

指標を決める

パフォーマンスの改善をおこなうために改善すべき目標の指標を決める必要がありますが、ページロードにおける指標は様々なものがあり、どの指標を改善すべきかはコンテンツの特性や目的によっても変わってきます。

例えば DOM のロード完了(DOMContentLoaded)や、サブリソースの取得まで含めたロードの完了(load)のイベントが発火するまでの時間はよく知られた指標の1つです。これらは簡単に取得できるというメリットがありますが、実際にページにコンテンツが表示されるまでの速度とは異なるため、改善の目安の1つとして使うのはよいですが、目標とする指標にするには不十分です。

DOM やリソースのロード時間と比べ、コンテンツが描画されたり、ユーザーが操作できるようなタイミングといった指標は、より実際のユーザー体験に近い指標を得ることができます。例えば以下のようなものがあります。

  • First Paint
    • 画面に何かしら(背景色などでもよい)描画されたタイミング
  • First Contentful Paint
    • テキストや画像などのコンテンツが最初に描画されたタイミング
  • First Meaningful Paint
    • ユーザーにとって意味のあるコンテンツが描画されたタイミング
  • Time To Interactive
    • ユーザーの入力に反応できるようになったタイミング

f:id:hokaccha:20181129161429p:plain
User-centric Performance Metrics | Web Fundamentals | Google Developers
Licensed under a Creative Commons Attribution 3.0 License.

First Paint と First Contentful Paint は簡単に機械的に判定できるものなので、ブラウザの API から取得できますし、標準化も進んでいます。一方、First Meaningful Paint や Time To Interactive は何を持って意味のあるコンテンツとするのか、ユーザーの入力に反応できる状態と判断するのか、という基準を決めるのが難しいので、曖昧さが残る指標ですが、実際のユーザーの体験に近い数値を取ることができます。

これらの指標が有効なケースも多いのですが、実際のブラウザによるページのロードはもう少し複雑で、ある特定のタイミングを測るだけでは不十分なケースも多くあります。そこで考えられたのが Speed Index という指標です。Speed Index は単純なある地点でのタイミングでなく、ファーストビューが表示されるまでの進捗を含んだ数値です。

f:id:hokaccha:20181129161758p:plain

上記の図において、A と B はファーストビューの表示速度は同じですが、A のほうは徐々にコンテンツが表示されており、B はファーストビューがでるまでほぼ真っ白な状態です。Speed Index は最終フレームと途中経過のフレームの差分を計算し、それを足し合わせることでスコアを算出します。そうすることで実際のユーザー体験により近い指標を得ることができます。上記のケースでは当然体験がよいのは A で、Speed Index のスコアも A のほうが低く(Speed Index は低い方がよい)なります。

もっと具体的な算出法方法については公式のドキュメントを参照してください。

Speed Index - WebPagetest Documentation

今回はこれらの指標を検討し、Speed Index を目標指標として採用することにしました。

Catchpointでの計測

Catchpoint では Speed Index の計測はデフォルトで有効になっていません。Advanced Settings から Filmstrip Capture を有効にすることで Speed Index を計測できるようになります。

f:id:hokaccha:20181129161843p:plain

Filmstrip Capture は特定の間隔で画面のキャプチャを取る機能で、このキャプチャを元に Speed Index が算出されます。Catchpoint ではこのキャプチャを取る間隔を 200ms 〜 2000ms で選ぶことができます。有効にして測定すると次のように、画面がレンダリングされていく様子がキャプチャで記録され、Speed Index のスコアが取得できます。

f:id:hokaccha:20181129161934p:plain

また、Speed Index 以外にも改善の助けとなる指標はたくさんあるので、それらをまとめてダッシュボードを作り継続して観測できるようにしています。

f:id:hokaccha:20181129162010p:plain

ページ遷移のパフォーマンス計測

ページロードのパフォーマンス改善は、初回アクセス時と別のページから遷移時、2度目のアクセス時などによって大きく性質がことなります。初回アクセス時には何もキャッシュを持っていない状態なのでクライアント側のキャッシュを使う方法は役に立ちません。一方、クックパッドのサイトで検索ページからレシピページに遷移するようなケースでは、検索ページにアクセスした時点で共通のアセットをキャッシュしたり、検索結果のレシピのページを先読みしてキャッシュしておくなどの対策が可能になります。

Catchpoint ではこのようなページ遷移時のパフォーマンスも測定することができます。

Transaction Test Type – Catchpoint Help

ページ遷移するためのスクリプトを設定に書くことができます。例えば検索画面にアクセスし、一番上のレシピをクリックしてレシピ画面に遷移するためには、以下のようなスクリプトを設定画面に書きます。

// Step - 1
open("https://cookpad.com/search/%E3%83%91%E3%82%B9%E3%82%BF")
setStepName("Step 1: Open Search Page")

// Step - 2
clickAndWait("//*[@id='recipe_0']/div[@class='recipe-text']/span[1]/a")
setStepName("Step 2: Transition To Recipe Page")

計測結果は各ステップごとに保存され、以下のように結果を見ることができます。

f:id:hokaccha:20181129162052p:plain

様々なキャッシュが効くので初期ロードのときよりも各種スコアがよくなっており、遷移時のほうが高速にページがロードされていることがわかります。

まとめ

Catchpoint を使ったWebページのパフォーマンス計測について紹介しました。パフォーマンスの改善についてはまだ着手し始めたばかりで、具体的な施策をおこなうのはこれからです。具体的な改善について成果がでたらまた別の機会に報告したいと思います。

/* */ @import "/css/theme/report/report.css"; /* */ /* */ body{ background-image: url('https://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527163350.png'); background-repeat: repeat-x; background-color:transparent; background-attachment: scroll; background-position: left top;} /* */ body{ border-top: 3px solid orange; color: #3c3c3c; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; line-height: 1.8; font-size: 16px; } a { text-decoration: underline; color: #693e1c; } a:hover { color: #80400e; text-decoration: underline; } .entry-title a{ color: rgb(176, 108, 28); cursor: auto; display: inline; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; font-size: 30px; font-weight: bold; height: auto; line-height: 40.5px; text-decoration: underline solid rgb(176, 108, 28); width: auto; line-height: 1.35; } .date a { color: #9b8b6c; font-size: 14px; text-decoration: none; font-weight: normal; } .urllist-title-link { font-size: 14px; } /* Recent Entries */ .recent-entries a{ color: #693e1c; } .recent-entries a:visited { color: #4d2200; text-decoration: none; } .hatena-module-recent-entries li { padding-bottom: 8px; border-bottom-width: 0px; } /*Widget*/ .hatena-module-body li { list-style-type: circle; } .hatena-module-body a{ text-decoration: none; } .hatena-module-body a:hover{ text-decoration: underline; } /* Widget name */ .hatena-module-title, .hatena-module-title a{ color: #b06c1c; margin-top: 20px; margin-bottom: 7px; } /* work frame*/ #container { width: 970px; text-align: center; margin: 0 auto; background: transparent; padding: 0 30px; } #wrapper { float: left; overflow: hidden; width: 660px; } #box2 { width: 240px; float: right; font-size: 14px; word-wrap: break-word; } /*#blog-title-inner{*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-position: left 0px;*/ /*}*/ /*.header-image-only #blog-title-inner {*/ /*background-repeat: no-repeat;*/ /*position: relative;*/ /*height: 200px;*/ /*display: none;*/ /*}*/ /*#blog-title {*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-image: url('https://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527172848.png');*/ /*background-repeat: no-repeat;*/ /*background-position: left 0px;*/ /*}*/