2013-02-01
GmailがハマったSPDYの落とし穴
1. SPDYブーム到来
おかげさまで、ここ数日 SPDY が私の周りで非常にブームになってきています。
前回案内したSPDY&WS勉強会は既に200名以上の申し込みがあり、今ではSPDYネタでブログを書くと非常に注目されるうれしい状況です。時代はまさに、
SPDYはハイプサイクルを順調に駆け上がっている
状況だと思います。
図1:2012年のハイプサイクル:
図はガートナー社のプレスリリース http://www.gartner.co.jp/press/html/pr20120906-01.html から引用
SPDYが、まだ黎明期に入ったばかりなのか、それとも既にピーク期に入ったのか、それは歴史が証明してくれるでしょう。
ということで勉強会までSPDY熱が冷めないよう、私もいろんなSPDYネタを出していきたいと思います。
2. GmailがハマったSPDYの落とし穴とは
先日、 Google でSPDYの開発の主要担当者をしている William Chan より、 SPDY Prioritization Case Study – Gmail といったブログが公開されました。非常に分量の多いエントリーですが、大きく以下の2つの話が書かれています。
- 「ChromeでGmailのCSSのダウンロードがJSより遅くなっている。なぜだか理由がわからない。」とGmailチームより相談された。→ 調べてみるとSPDY の優先度設定が原因だった。
- SPDYの優先度設定は、現状の仕様ではまだ不十分なので考え直そう。
今回、前者の話について実際に手元でシミュレーションをした結果とその理由を解説したいと思います。(大元のブログを読んで内容を理解した方は、わざわざこの後を読まれる必要はありません。)
3. Gmailのページ読み込み最適化手法
まずGmailがどのようにしてページ読み込みの最適化が行われているか、その資料のポインターが示されています。
Browser Enhancements to Help Improve Page Load Performance Using Delta Delivery
これ読んで驚きましたね。
Gmailは iframe を使って JS を読み込み、その中の AjaxでCSSをJSON形式でダウンロードしている。
とのこと。もともとの資料は、W3Cにて DeltaJS について提案したものです。この DeltaJS とは、JSのアップデート差分を送る技術仕様です。
ぶったまげました。しかし、ここに書いてあるGmailの読み込み最適化手法やDeltaJSについては、もう一つや二つブログが書けるネタなので、今回触れるのはこのくらいにしておきます。先のブログでは、Gmailの場合Ajaxで非同期に読み込まれる60KBの圧縮されたCSSのダウンロードが900KBの圧縮されたJSより遅いのは何故だろうか? というのがGmailチームの悩みだったようです。
4. Gmailのページ読み込みをシミュレーションしてみる。
ということで、Gmailのページ読み込みのシミュレーションをしてみましょう。
以下の3種類のファイル(index.html/ifram.html/css.json)を用意して Chrome から SPDY を使って index.html にアクセスしてみます。index.htmlに含まれる iframe.html のサイズは巨大なJSコメントを含んだ1.1Mbyte。一方 css.jon の方は、わずか40byteです。SPDYの情報を取れるようサーバは spdylay の spdyd を使いました。
<!-- index.html --> <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8" /> <title>SPDY Priority Test</title> </head> <body> This is a test page. <iframe src="iframe.html"></iframe> </body> </html>
<!-- iframe.html --> <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8" /> <title>IFrame</title> <script> (function() { var request = new XMLHttpRequest(); request.open("GET", "https://spdy-int.iijplus.jp:8443/css.json"); request.send(); })(); </script> <script> /* aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa */ /* aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa */ /* 以下コメントがいっぱい 1M byte 程続く */ </script> </head> <body> Iframe </body> </html>
css.json
{"css" :"#hoge {color: red;}"}
iframe.html の最初で読み込んだSCRIPT文で Ajax が非同期で直ちに実行されるので、1.1MbyteのJSを含む iframe.html のダウンロードが終わる前に、たった 40byte の css.json のダウンロードは当然完了しているだろうと予想します。
結果は、
CSSのダウンロードがJSより遅くなっている!
Ajax全然意味ないじゃん!
ということで、Gmailチームが悩んでいた問題の再現に成功しました。
5. SPDYの優先度とは
ここでW. Chan は、これを SPDY の問題であると見つけ出すのですね。さすがです。実は Chrome のSPDY優先度設定が原因でした。
SPDYでは、リクエスト毎に0-7の8段階の優先度設定ができます。SPDY の優先度フィールドどう設定されているのかは、以下のスライドの p13、 SYN_STREAM のプロトコルフォーマット表を参照して下さい。
で、Chrome側の実装では、リソースのタイプによって優先度を HIGHESTからLOWESTの5段階に分けていたんですね。それを表にすると以下の通りになります。
表1:ChromeのSPDY優先度設定 | |||
優先度カテゴリ | 優先度 | リクエストタイプ | 説明 |
---|---|---|---|
HIGHEST | pri=0 | MAIN_FRAME | メインページ |
SUB_FRAME | iframe | ||
MEDIUM | pri=1 | STYLESHEET | スタイルシート |
SCRIPT | JavaScriptファイル | ||
FONT_RESOURCE | フォント | ||
LOW | pri=2 | SUB_RESOURCE | MEDIUM以外のリソース |
OBJECT | オブジェクト要素 | ||
MEDIA | メディア要素 | ||
WORKER | ワーカ | ||
SHARED_WORKER | 共有ワーカ | ||
XHR | Ajax | ||
LOWEST | pri=3 | IMAGE | 画像 |
FAVICON | favicon | ||
IDLE | pri=4 | PREFETCH | プリフェッチ |
実際に spdyd の出力で確認してみましょう。
iframe.html
[id=3] [ 19.616] recv SYN_STREAM frame <version=3, flags=1, length=118> (stream_id=3, assoc_stream_id=0, pri=0) :host: spdy-int.iijplus.jp:8443 :method: GET :path: /iframe.html :scheme: https :version: HTTP/1.1 (以下略)
css.json
[id=3] [ 19.735] recv SYN_STREAM frame <version=3, flags=1, length=128> (stream_id=5, assoc_stream_id=0, pri=2) :host: spdy-int.iijplus.jp:8443 :method: GET :path: /css.json :scheme: https :version: HTTP/1.1 (以下略)
表1の通りiframe.html は SUB_FRMAME なので優先度はHIGHEST(pri=0)です。一方CSSの方は Ajax による json 形式で取得しているので LOW(pri=2)なんですね。
6. Gmail がハマった理由
この優先度設定を先ほどのシミュレーション結果に当てはめてみます。
これで問題の原因があきらかです。
AjaxによるJSON形式のCSSデータの取得は、iframeで取得するJavaScriptよりSPDYの優先度が低いためCSSのダウンロードの完了がJSより遅い
ということです。このため、いくらAjaxで非同期処理にしても、わずかCSSのサイズが40byteしかなくても、CSSのダウンロードの完了がiframe中のJSのダウンロードより遅れてしまうということが常に発生しているのです。結局、
JSをiframeでダウンロードし、cssを Ajax経由の json でダウンロードするといった Gmail の(ある意味特殊な)最適化手法がChromeのSPDY優先度設定に影響されてしまった
というオチだったんですね。ここで試しに、iframe.html を以下のように変更してみます。
<!-- iframe.html --> <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8" /> <title>IFrame</title> <script src="iframe.js"></script> <link rel="stylesheet" href="css.css" type="text/css"> </head> <body> Iframe </body> </html>
iframe.jsは、1Mbyte近くのJSコメントのみ、css.css は、先程の css.json の CSSだけ入っています。いわゆる通常のページ(script要素で JS、 link要素で CSS をダウンロード)の場合です。
その結果は、
です。(SPDY優先度値も加えています。)
おぉ、これは予想通り JSとCSSが並んでダウンロードが完了しています。 普通のページは、こんな感じになるんでしょう。
しかし、小さなCSSがJSに引きずられている感はあります。こういった部分を改良することが今後必要だというのがブログの後半部分です。一昨日からGoogle Japan で開催されていた HTTP/2.0 の interim meeting でこの点について議論がされたようですので、その様子の報告を楽しみに待ちたいと思います。(spdy/4では、 Stream Dependencies という仕様が現在提案されています。)
そして、昨日 Google で開催された Chrome Tech Talk Night #5 の後、講演者で Chrome Developer Advocate の Ilya Grigorik さんと直接SPDYの話をする機会がありました。GoogleのSPDYの取り組み状況やGmailチームの大変な苦労などお聞きして非常に参考になりました。(Private Comminication なので詳細は書きませんが。)既に2年以上SPDYをサービス提供しているGoogleでもこのような落とし穴にハマることがあるんだなぁ、と意外に思うと同時に、
やはりSPDYを本当に使いこなすには、しっかりした運用ノウハウの蓄積が欠かせないものだ
と強く感じた次第です。
- Twitter / @jovi0608
- Twitter / @agektmr
- Twitter / @masayadk1229
- Twitter / @yukotan
- Twitter / @nakajmg
- Twitter / @takeshiyako
- Twitter / @atsuya
- Twitter / @mapoyon
- Twitter / @gakuzzzz
- Twitter / @abdndgdn
- Twitter / @voluntas
- Twitter / @gab_km
- Twitter / @Jxck_
- Twitter / @hiro345
- Twitter / @nari_ex
- Twitter / @iyken
- Twitter / @heroween
- Twitter / @_takamin_
- Twitter / @seratch
- Twitter / @letsspeak
- Twitter / @salhasa
- Twitter / @hide_zebra
- Twitter / @YujiRS
- Twitter / @Shumpei
- Twitter / @openspc
- Twitter / @_HODA
- Twitter / @mstssk
- Twitter / @tori3_jp
- Twitter / @kaztr
- Twitter / @nekogeruge_987
- Twitter / @goto_ipv6
- Twitter / @seiitirur
- Twitter / @yteraoka
- Twitter / @morozumi_h
- Twitter / @knt_mr
- Twitter / @fumio_naito
- Twitter / @meganetops
- Twitter / @yukihr
- Twitter / @yuzukun
- Twitter / @M_Ishikawa
- Twitter / @ARS_2000
- Twitter / @joukan_jakusha
- 1594 http://b.hatena.ne.jp/
- 697 http://www.hatena.ne.jp/
- 581 http://gigazine.net/news/20130201-headline/
- 510 http://b.hatena.ne.jp/hotentry
- 488 http://www-ig-opensocial.googleusercontent.com/gadgets/ifr?exp_rpc_js=1&exp_track_js=1&url=http://www.hatena.ne.jp/tools/gadget/bookmark/bookmark_gadget.xml&container=ig&view=default&lang=ja&country=JP&sanitize=0&v=5dd8eb8f1e9514d&parent=htt
- 327 http://b.hatena.ne.jp/hotentry/it
- 247 http://b.hatena.ne.jp/entry/d.hatena.ne.jp/jovi0608/20130201/1359679098
- 245 http://reader.livedoor.com/reader/
- 180 http://hatebu.straightline.jp/
- 171 http://t.co/y9aOy0Rk