Webサイトパフォーマンスについて

Webサイトのパフォーマンスについて記事を書いています。パフォーマンス管理は、品質管理です。ですから計測データを元に記事を書いてます。

はてなブログを自分で出来る範疇で高速化してみる

はてなブログの高速化について、はてなスターを外すと速くなるとか、色々話題になっています。

ユーザが手を入れられる範囲でどこまで高速化できるか、いつも私がやっている統計的品質管理のアプローチで、計測・分析・改善してみました。

デスクトップサイト計測

まずは、現状把握、Synthetic Monitoringです。 Synthetic Monitoringとは、実験計画法のフィッシャー三原則に則った、対象ページに介在して計測する手法です。 一ユーザとして、こちら側から、一定間隔で、対象ページにアクセスをして、表示速度に関するデータを取得します。

計測対象サイト

  • takehora.hatenadiary.jp

トップに乗っていた記事は、5.3MBあって、かなり重いです。 f:id:takehora:20170718185956p:plain グラフ関係の画像を多用しているからですね。

計測条件

  • 日本の帯域保証型(100Mbps)光回線 … NTTとKDDI
  • 計測ブラウザ … Chrome 53
  • 計測頻度 … 15分に1回
  • 計測期間 … 7月9日~15日の7日間
  • 計測ツール … Catchpoint

Catchpointを知らない方のために説明しますと、CatchpointはWebサイトのパフォーマンスを24時間365日定常監視・計測するためのサービスを提供している企業です。 f:id:takehora:20160614110855p:plain Googleの品質保証担当Vice PresidentだったMedhi Daoudiが2010年に立ち上げた企業で、現在、GoogleMicrosoftなどのテクノロジー企業、AkamaiやFastly、MaxCDNなどのCDN各社、Verizonなどの通信企業など、数多くの企業が利用しているサービスです。

ちょっと宣伝させて頂くと、現在、日本については私の会社Spelldataで販売しております。

分析

ダウンロード時間

まずは、ダウンロード時間の散布図を見ます。

f:id:takehora:20170716100006j:plain

はてなブログは、NTTよりKDDIの方が高速にダウンロードできているのが分かります。 大体、双方ともに6.5秒前後といったところです。 時折、17秒近くまで遅延しているのが分かります。

積分布関数で見てみましょう。

f:id:takehora:20170716100708p:plain

このグラフからも、NTTの方がKDDIよりも遅い事が分かります。 それでは、どのくらいの割合の人が遅延を経験するのでしょうか? それは、グラフの変曲点を見れば分かります。

変曲点とは、平面上の曲線で曲がる方向が変わる点の事です。

f:id:takehora:20170716101236p:plain

NTTでは、94パーセンタイルのところで曲がり具合が変わります。 NTTの回線を使っているユーザは、6パーセントの確率で、著しい遅延を体験しているであろうという事が言えるわけです。

表示開始時間

表示開始時間の散布図を見ます。

f:id:takehora:20170716103041p:plain

NTT、KDDI共に、1.5秒前後で表示開始していることが分かります。

ヒストグラムで品質を確認します。

f:id:takehora:20170716103351p:plain

すると、左右対称の分布を描いているのが分かります。

このグラフから、最頻値がNTTで1.4~1.5、KDDIで1.5~1.6秒であることが分かります。 世界的には、表示開始時間は0.5秒が目標値とされているので、あと1秒縮めたいです。

積分布関数で見ると、NTTの回線を使用しているユーザは、1パーセントの確率で、表示が非常に遅い体験をしているであろうことが分かります。

f:id:takehora:20170716104655p:plain

表示完了時間

表示完了時間の散布図を見ます。 表示完了とは、Document Completeの値を見ています。

f:id:takehora:20170716105624p:plain

KDDIは5.7秒前後、NTTは6.6秒前後で表示完了していることが分かります。

ヒストグラムで品質を確認します。

f:id:takehora:20170716110325p:plain

すると、KDDIの最頻値は5.5~6.0秒、NTTの最頻値は6.0~6.5秒です。 世界的には、表示完了時間は2秒が目標値とされているので、あと3~4秒縮めたいです。

積分布関数で見ると、NTTの回線を使用しているユーザは、6パーセントの確率で、著しい表示完了の遅延を体験しているであろうことが分かります。

f:id:takehora:20170716110600p:plain

ホスト単位で分解する

昨今のWebページは、複数のドメイン、ホストからの配信で出来上がっています。 それは、はてなブログも同様です。

そこで、はてなブログを構成するオブジェクトを配信しているホスト単位でパフォーマンスを確認していきます。

platform.twitter.com

まずは、platform.twitter.com です。

f:id:takehora:20170716111709p:plain

速いときは、100~200msぐらいでレスポンスを返すのですが、遅い時は、12秒まで遅延します。

積分布関数で見ると、以下のようになります。

f:id:takehora:20170716112102p:plain

96パーセンタイルが変曲点なので、遅延を引き起こす要因としては、4パーセントです。 スパイクすると、酷い遅延を引き起こすため、これは外さざるを得ないです。

cdn.image.st-hatena.com

画像の配信に使われているホストです。実際は、CDN大手のAkamaiです。

まずは、パフォーマンスを経時データで確認します。

f:id:takehora:20170716112801p:plain

Akamaiは基本的に高速なのですが、1.3~1.7秒までの遅延が頻発しており、15秒超のスパイクが発生しています。

積分布関数で見ると、以下のようになります。

f:id:takehora:20170716112935p:plain

ここは、はてなブログの仕組み上、ここは手を付けられないので、そのままにするしかないです。

apis.google.com

GoogleAPIサーバです。

f:id:takehora:20170716113755p:plain

定常的に、0.6~0.7秒のレスポンスで、時折、4秒前後のスパイクが発生しています。

f:id:takehora:20170716115208p:plain

変曲点は、99パーセンタイルで、1パーセントの確率で著しい遅延要因となりますが、定常的に0.6~0.7秒掛かっているので、いずれにせよ、外さないと駄目です。

cdn7.www.st-hatene.com

これは、jQueryJavaScriptを配信しているサーバです。実際はAkamaiです。

f:id:takehora:20170716120437p:plain

スパイクしているときは、15秒まで遅延しています。

f:id:takehora:20170716120508p:plain

積分布関数で見ると、変曲点は99パーセンタイルで、1パーセントの確率で遅延を引き起こしています。 ここは、はてなブログの仕組み上、手を付けられないので、そのままにするしかないです。

connect.facebook.net

これは、Facebookの「いいね!」ボタンに必要なJavaScript SDKをダウンロードするホストです。

f:id:takehora:20170716121201p:plain

通常は、300msぐらいで配信していますが、スパイクが二段階発生しています。

一段階目のスパイクは、1.5秒前後で、これは頻発しています。二段階目のスパイクは、7秒前後で、一週間で3回観測されています。

f:id:takehora:20170716121654p:plain

積分布関数で見ると、89パーセンタイルが変曲点です。つまり、11パーセントの確率で著しい遅延を引き起こしています。 このJavaScriptは、約63KBで、この容量であれば、日本国内であれば、50~70msぐらいでダウンロードできるはずです。 動的処理が入ったとしても、100msぐらいで返して欲しいものです。

counter.hatena.ne.jp

はてなカウンターのホストです。

はてなカウンターは、2017年8月7日を以って、サービスの提供が終了されるそうです。

f:id:takehora:20170716124002p:plain

通常は50ms前後でレスポンスを返していて、時折、1秒ぐらいまでスパイクします。 アクセス解析のサービスとしては高速だと思います。

f:id:takehora:20170716123614p:plain

87パーセンタイルが変曲点です。

csi.gstatic.com

csi.gstatic.comは、Googleの静的ファイルの配信用のホストです。

f:id:takehora:20170716125716p:plain

定常的に500~600msのレスポンスです。 以前に比べると、かなり改善されました。 前は、もっと遅かったです。

こんな議論もあったくらいです。

csi.gstatic.com is your weakest link, Google. Why? https://productforums.google.com/forum/#!topic/picasa/ZN-xUwMRRKo

f:id:takehora:20170716130113p:plain

積分布関数で見ると、特に著しい遅延が発生しているわけではないですが、定常的に遅いです。

staticxx.facebook.com

staticxx.facebook.comは、「いいね!」や「シェア」に関する静的ファイルを配信するホストです。 個別データが入っているため、ダウンロードには認証が必要になっています。

f:id:takehora:20170716131347p:plain

速い時と、遅い時の、剣山状のグラフになっています。 こういうグラフが出るときは、大抵は、サーバ側の処理での負荷パターンに依存していることが多いです。 負荷パターンというのは、アクセスによる負荷ではなく、内部処理負荷です。 350ms~1.5秒前後の幅があります。

f:id:takehora:20170716131721p:plain

積分布関数で見ると、なだらかに右肩上がりです。定常的に遅いです。

www.google.com

https://www.google.com/recaptcha/api.js を配信しています。

詳細は、こちらをどうぞ。 reCAPTCHA V2  |  reCAPTCHA  |  Google Developers

f:id:takehora:20170716132714p:plain

通常は150~300msでレスポンスを返しているのですが、時折、1秒を超えます。

f:id:takehora:20170716133006p:plain

積分布関数で見ると、98パーセンタイルが変曲点なので、2パーセントの確率で遅延を引き起こしています。

www.hatena.ne.jp

www.hatena.ne.jpから何か引っ張ってきてページに入れ込んでいるようです。

f:id:takehora:20170716133252p:plain

結構な割合で、7秒超のスパイクを引き起こしています。

f:id:takehora:20170716133333p:plain

積分布関数で見ると、98パーセンタイルが変曲点です。 経時データでは、ぐんっ!と遅延が伸びているので、凄く目立ちますが、実際は2パーセントの確率で遅延を引き起こしています。

もう少し、詳細を見てみましょう。 何か、特定のファイルやリクエストが遅延を引き起こしているのでしょうか?

Catchpointでは、リクエスト単位の分析も可能で、それで分析すると、 https://www.hatena.ne.jp/notify/notices.count.json が遅延を引き起こしている事が分かります。

f:id:takehora:20170718203832p:plain

これは、外さないとまずいですね。

ちなみに、このリクエストをネットワークの要素分解すると、こんなグラフになります。

f:id:takehora:20170718203906p:plain

はてなブログの開発の方には、是非、参考にして改善して頂きたいです。

改善する

以上の計測データの分析から、

の二つが明確になりました。

そこで、これを外してみます。

サードパーティコンテンツを外す

SNSに関連するボタンなどを全て外します。

管理画面 → デザイン → カスタマイズに行き、記事のところのSNS関連、はてなスターのチェックを全て外します。

f:id:takehora:20170716134855p:plain

この作業によって、以下のホストが読み込まれなくなりました。

まだ残っているサードパーティコンテンツのホストは、以下の通りです。

  • www.gstatic.com
  • www.googletagmanager.com
  • www.google.com
  • www.google-analytics.com
  • platform.twitter.com
  • fonts.gstatic.com
  • fonts.googleapis.com
  • apis.google.com

この作業によって、サードパーティコンテンツのスパイクの影響が排除されました。

f:id:takehora:20170717123859j:plain

このグラフで、サードパーティコンテンツを外した後に、遅延が目立った箇所があります。 ピンク色の線の箇所ですね。 cdn.blog.st-hatena.comです。

実体は、Akamaiからの配信です。

f:id:takehora:20170717124129p:plain

ここから、複数のオブジェクトを配信しているのですが、その内、遅延が目立つものだけを抜き出したのが、以下のグラフです。

f:id:takehora:20170717124906p:plain

以下のオブジェクトについて、グラフにしています。

この中の、hatenablog.js が最も遅延しています。これは355,174バイトあります。 この程度の容量であれば、100ms前後で配信できて良いはずです。

https://cdn.blog.st-hatena.com/js/hatenablog.js?version=3fbf4667777c147506bf2767c1072c6752e44a08&env=production

というQuery String付で配信されているため、Akamaiでキャッシュされていないのかもしれません。

react-dom.min.jsもちょくちょくスパイクしています。

これも、

https://cdn.blog.st-hatena.com/js/external/react-dom.min.js?version=15.4.1

というQuery String付で配信されているため、Akamaiでキャッシュされていないのかもしれません。

いずれにせよ、これらは、テンプレートに組み込まれているため、手を出せないです。

以上の作業によって、表示開始時間と表示完了時間は、以下のように変化しました。

f:id:takehora:20170717131321p:plain

  • 表示開始時間 … ほぼ変わらず
  • 表示完了時間 … 6秒から4.8秒へ
  • ダウンロード完了時間 … 6.8秒から4.8秒へ

表示開始時間の改善

表示開始時間は、相変わらず、1.5秒前後のままです。 Waterfall図を見ると、以下のようになっています。

f:id:takehora:20170717134348j:plain ダウンロードに、間が空いているのが分かります。

ここからは、ChromeのDeveloper Toolを使い、ダウンロード関連の「秒の世界」から、描画関連の「ミリ秒の世界」へと入ります。

Chrome 59.0.3071.115 (64bit版)のDeveloper Toolで見ると、以下のようになっています。

f:id:takehora:20170718150333p:plain

Catchpointの計測環境と、私の使っているPCの環境は大きく異なるため、数値もCatchpointのWaterfall図とは異なる点をご留意ください。

また、ご自身で試される場合は、必ず、シークレットウィンドウを開いて、拡張機能の影響を排除し、キャッシュが効いていない状態で行って下さい。 再度読み込む場合は、Developer Toolの「ネットワーク」のタブの「disable cache」にチェックを入れてください。

※ disable cacheについて教えて頂いた山本悠滋‏さんに感謝です。

この図の例では、以下のような数値になっています。

  1. HTMLのダウンロード。 … 301ms
  2. CSSのダウンロード。blog.cssとテーマ用CSSのc0b82a0d884fdb6e0c3ebe84f82c15ca40d1d3e2の二つ。 … 154ms
  3. DOMツリーとCSSOM(CSSオブジェクトモデル)ツリーを組み合わせてレンダリングツリーを構築 … 182ms
  4. 表示開始 (First Meaningful Paint)

合計で、約630msほど使っています。

ここで注目して頂きたいのが、HTMLのダウンロードから、この表示開始までの間に、他の余分な要素が介在していない点です。 つまり、殆ど手のつけようがないというわけです。

やるとすれば、テーマ用CSSをよりシンプルにまとめて、CSSOMツリーの構築を高速化するくらいです。 しかし、182msより縮めたとしても、短縮できるのは数10msぐらいで、人が認知できるだけの効果は得られないでしょう。

というわけで、現状、表示開始時間の改善で出来る事は無いです。

表示完了時間の改善

次に表示完了時間までのプロセスを見ていきます。

f:id:takehora:20170718151936p:plain

大きく二つの処理から成り立っています。

どちらも、JavaScriptの処理です。

実は、この二つのHTMLのパース処理で、同じJavaScriptの処理が走っていて、非常に勿体ない時間の使い方になっています。

グローバルヘッダの付加は、一昔前であれば、SSI(Server Side Include)で処理したものです。 ここの実装は、是非、運営側で見直して欲しいものです。

Google Tag ManagerなどのJavaScriptも時間を消費していますが、一番重いのは、hatenablog.jsで、283msを消費しています。 これが2回実行されるわけですから、実装としては美しくないと考えます。

表示完了時間の短縮については、残念ですが、ユーザサイドで手を出せるものはないです。

改善後の結果を確認する

ダウンロード時間

f:id:takehora:20170718153244p:plain

ダウンロード時間は、改善後、全体的に3秒、下方へずれました。

表示開始時間

f:id:takehora:20170718153423p:plain

表示開始時間については、ほぼ変わらずです。

表示完了時間

f:id:takehora:20170718154029p:plain

表示完了時間については、改善後、全体的に1秒、下方へずれました。

モバイルサイトへの影響

このデスクトップサイトの変更は、モバイルサイトには何か影響を及ぼしたでしょうか?

リアル4G回線でも、モバイルサイトを計測してみました。

ダウンロード時間

f:id:takehora:20170718154831p:plain

一番安定して高速に配信しているのは、SoftBankです。その次がKDDIで、Docomoは定期的にスパイクが発生しているのが分かります。

これを見て分かるのは、全く、変更作業の影響が、モバイルサイトでは及んでいない事です。

表示開始時間

f:id:takehora:20170718155451p:plain

表示開始時間は、キャリアによって、バラツキの差がありますが、おおむね、1秒ぐらいです。 これは、デスクトップサイトより高速です。

表示完了時間

f:id:takehora:20170718155730p:plain

表示完了時間も、キャリアによって、バラツキの差がありますが、デスクトップサイトより高速です。

ヒストグラムにして、最頻値を見ると、以下のとおりです。

f:id:takehora:20170718160233p:plain

いずれにせよ、デスクトップサイトの変更の影響は出ていません。

デスクトップでは、5.3MBあった容量ですが、モバイルでは1MBです。

f:id:takehora:20170718190127p:plain

はてなブログのモバイルのトップページは記事一覧であるため、画像もサムネイルで小さく、容量が必然的に小さくなるのです。

まとめ

以上、データで見てきたように、ユーザサイドで高速化のために出来ることは少ないです。

今回、この記事を書いたきっかけは、他の方が書かれた、はてなブログの高速化についての記事でした。

その記事でも、高速化の方策のヒントとされていたのはGoogle Page Speed Insightsです。

そのGoogle Page Speed Insightsで、改善前のページの診断は以下の通りでした。

f:id:takehora:20170716095256j:plain

デスクトップサイトは、「Poor、27/100」と診断されます。

これが改善後、どうなったかというと、以下のとおり、全く変わりません。

f:id:takehora:20170718181458p:plain

モバイルは、改善前・改善後、共に変わらず、「Needs Work 65/100」です。

f:id:takehora:20170718181551p:plain

デスクトップサイトの高速化はある程度できたのに、何故、スコアが変わらないのでしょうか?

それは、ちゃんとPage Speed Insightsのガイドに書いてあります。

ただし、ネットワーク接続のパフォーマンスは大きく変動するため、PageSpeed Insights では、ページのパフォーマンスのうちネットワークに依存しない部分(サーバー設定、ページの HTML 構成、画像やJavaScriptCSS などの外部リソースの使用方法)のみを考慮します。提案された解決策を実装すれば、ページの相対的なパフォーマンスは改善されるはずです。ただし、それでも、ページの絶対的なパフォーマンスはユーザーのネットワーク接続に左右されます。

基本的に、Page Speed Insightsは、ネットワーク要因は診断していません。 レンダリングに関する要因をチェックしています。

しかし、Webパフォーマンス(表示速度)の遅延要因の8割は、ネットワーク要因です。 それも、サードパーティコンテンツが大きな割合を占めることが多いのです。

ですから、私が、皆さんに提案したいのは、「まずは秒の世界の改善(ネットワーク要因・サーバ要因・サードパーティコンテンツ)、そしてミリ秒の世界の改善(レンダリング)」です。

それと、影響を及ぼす事の出来る範囲を明確にして改善することです。 はてなブログについては、ユーザ側で影響を及ぼす事が出来る範囲は狭いです。

自動診断やベストプラクティスを鵜呑みにして、あれもこれもと試すと、逆に遅延してしまうのです。

はてなスター

皆さんが、遅延を懸念されていた「はてなスター」ですが、入れても入れなくても、基本的にはパフォーマンスには影響ないです。

f:id:takehora:20170718184929p:plain

表示完了後に読み込まれていますし、4~11msと非常に高速に処理されています。

でも、長期でみると、時折遅延しています。 一週間で見ると、https://s.hatena.ne.jp/js/HatenaStar.jsは3秒まで遅延していますね。

f:id:takehora:20170718205224p:plain

遅延要因は、色々です。

f:id:takehora:20170718205346p:plain