「ハイパフォーマンス ブラウザネットワーキング」を読んだ。の続き

前回は「14章 ブラウザネットワーキング入門」、「15章 XMLHTTPRequest」を扱いました。 www.developers-helix.info

今回は「9章 HTTPの歴史」から「13章 アプリケーション配信最適化」をまとめます。

9章 HTTPの歴史、11章 HTTP 1.x、12章 HTTP2.0

HTTP 0.9

  • HTMLのみ転送可能
  • リクエストはメソッドとパスのみ
  • ドキュメントの転送が完了すると接続は終了する
  • ApacheやNginxなどのWebサーバーは現在もHTTP0.9をサポートしている。
GET /about/

HTTP 1.0

  • HTML、プレーンテキスト、画像、その他形式の転送が可能(Hypertext TransferというよりはHypermedia Transportと呼べる存在に)
  • リクエストはメソッド、パスのほか、複数の改行されたヘッダーフィールドを持てる
  • サーバーとクライアントのそれぞれのリクエスト後に終了する
  • ほとんどのWebサーバーでHTTP 1.0をサポートしている。ただしリクエストごとに新規TCP接続を必要とするので、パフォーマンスの低下を引き起こす。
GET /about/ HTTP/1.0

HTTP 1.1

  • パフォーマンスの最適化を取り入れた
    • キープアライブ接続: 同じTCP接続を使い回せる
    • チャンク転送コーディング: データをぶつ切りにして、部分的に送信開始できる。
    • バイトレンジリクエスト: 取得したいコンテンツの範囲を取得できる(データのうち200-400byteまでなど)

HTTP 2.0

  • Googleによって開発された実験的なプロトコルであるSPDYがベース
  • 追加された機能
    • ストリームの多重化: 単一のTCP接続内で多数のストリームが並列にリクエストを送信できる。(HTTP1.1までは1つのリクエストが完了するまで、原則次のリクエストを送ることができなかった)
    • フロー制御: ストリームごとに受信可能なバイト数の通知を行うことで帯域幅への競合を防ぐ。(TCPのフロー制御とほぼ同じ仕組み)
    • サーバープッシュ: クライアントからの1つのリクエストに対して複数のレスポンスを返すことができる。ドキュメントに関連するCSSJavaScript、画像などのリソースをサーバー側から送りつけてしまうことでリクエストの数を減らすことで発生するはずだったレイテンシを排除できる。
    • ヘッダ圧縮: ヘッダテーブルをクライアントとサーバーに用意することでヘッダの差分のみを送る。(通常HTTP1.xのヘッダは1リクエストあたり500-800バイトほどオーバーヘッドが発生していた。)

10章 Webパフォーマンス入門

ハイパーテキスト、Webページ、Webアプリケーション

  • ハイパーテキスト: ハイパーリンクを付与したプレーンテキスト
  • Webページ: 画像や動画を含めたリッチなレイアウトが可能となったコンテンツ
  • Webアプリケーション: Javascript、DHTMLやajaxによるインタラクティブなコンテンツ
  • Web関連技術の進化とともにWebサイトを構成するリソースのサイズ、それらを取得するリクエスト数が増加している。
  • 数百のリソース、数MBのリクエストを複数のホストから取得するという処理を数百ミリ秒以内に行うことが必要。

スピード、パフォーマンス、人間の知覚

  • 時間とユーザーの知覚
    • 0-100ms: 瞬時
    • 100-300ms: わずかな知覚可能な遅延
    • 300-1,000ms: マシンが動作している
    • 1,000+ms: メンタルコンテクストスイッチが発生する(他のことが頭をよぎる)
    • 10,000+ms: タスクを破棄
  • アプリケーションが瞬時に反応したと感じさせるためには数百ミリ以内にレスポンスを行わなければならない。ただしDNS解決、TCPハンドシェイクなどのネットワークのオーバーヘッドだけでその大半を使ってしまう。
  • 例えばhttp://www.yahoo.jpの表示には683msかかり、そのうち30%の200msがネットワークのオーバーヘッド。

ブラウザ最適化

  • ブラウザ自体にもパフォーマンスを向上させるための仕組みが実装されている。
    • ドキュメント認識最適化: リソースの優先度付け、先読み解析によって初回のレンダリングに必要なリソースを始めに取得してユーザーが操作可能な状態にする。
    • 投機的最適化: ユーザーのナビゲーションパターンを認識してDNS事前解決やTCP事前接続を行うことで、ユーザーが実際にアクセスした際にかかる時間を短縮する。
  • Webアプリケーションの開発者は以下の手法でブラウザによる最適化を補助できる。
    • レンダリングに重要なリソース(CSSJavaScriptなど)は先に読み込まれるよう上の方に記載する。
    • ドキュメントはサーバー上で生成され次第、部分的にでも送信する。(Google検索では検索クエリの解析の前に検索ページのヘッダー部分のドキュメントを送信している)
    • ヒントをドキュメントに埋め込み、最適化を施す
<link rel="dns-prefetch" href="//hostname_to_resolve.com">(DNS事前解決)
<link rel="prefetch" href="/images/big.jpg">(リソースのプリフェッチ)
<link rel="prerender" href="//example.org/next_page.html">(指定ページのプリレンダリング)

13章 アプリケーション配信最適化

定番のパフォーマンスベストプラクティス

  • 不要なネットワークレイテンシを排除
    • DNSルックアップを減らす
    • TCP接続内接続の再利用
    • HTTPリダイレクトを減らす
    • 必要ないリソースを排除する
    • リクエストやレスポンス処理の並列化
    • プロトコル特有の最適化を適用(HTTP1.xのドメインシャーディングなど)
  • 通信データ量を最小化
    • リソースをクライアントにキャッシュ
    • 転送中リソースの圧縮
    • リクエストから不要なデータを排除