レイテンシーの闇を克服せよ

問題に直面した時はいつも人々は集まって回避策を考えます。中には使いやすい案もあるし、ゴミのように役に立たない案もあります。

3.1 スプライティング

小さな画像をより集めて一つの大きな画像に結合することをスプライティングと言います。JavaScriptやCSSを使って大きな画像から個々の小さな画像を"切り取り"表示させるのです。

サイトはこのトリックを速度向上のために使います。HTTP 1.1では1つの大きな画像をダウンロードするほうが100個の小さな画像をそれぞれダウンロードするよりもはるかに高速です。

もちろんこれには不利なところがあって、それは小さな画像の1個か2個程度しか表示しないサイトの場合です。キャッシュからはすべての画像が一度に削除されてしまうことになり、よく使う画像だけをキャッシュに残すといったことができないのです。

3.2 インライニング

インライニングは個々の画像を送信することを回避する別のトリックで、CSSファイルに埋め込んだdata: URLを使います。これはスプライティングと同じ長所と短所を持っています。

.icon1 {
background: url(data:image/png;base64,<data>) no-repeat;
}
.icon2 {
background: url(data:image/png;base64,<data>) no-repeat;
}

3.3 コンカチネーション

大きなサイトではたくさんのJavaScriptファイルを使っています。開発者はフロントエンドのツールを使って全てのファイルを一つの大きなファイルに結合します。ブラウザーは個々のファイルをダウンロードするのではなく結合した一つのファイルだけをダウンロードするのです。ほんの一部だけをほしい場合でも巨大なファイル全体が送信されるのです。ほんの一部でも変更されると、巨大なファイル全体をリロードする必要があります。

このプラクティスはもちろん開発者にとって厄介なことなのです。

3.4 シャーディング

ここで紹介する最後の性能を向上させるトリックは"シャーディング"と呼ばれているものです。これは基本的にサービスの機能をできるだけ多くのホスト上に分散して配置することです。初見では少し奇妙に見えるかもしれません。しかしその背景には健全な理由があるのです。

初期のHTTP 1.1の仕様書はクライアントが各ホストへ確立できるTCP接続数を最大2個としていました。この仕様を破らないようにするため賢いサイトは単純に新しいホスト名を発明したのです。するとどうでしょう、サイトへの接続数は増え、ページロード時間を削減することができたのです。

時を経てこの制限は削除され、今日においてクライアントはホスト名毎に6-8接続を使っています。しかしこの接続数に制限があるのは変わりないので接続数を増やすためにサイトはこのトリックを使い続けています。先に示したようにオブジェクトの数が増えるにつれて、HTTPを効率よく機能させサイトを高速化するためだけに多くの接続が使われているのです。50以上、時には100を超える接続がひとつのサイトで使われる、ということも珍しいことではありません。httparchive.orgの最近の統計は世界トップ300K個のURLにおいて、平均40(!)個のTCP接続がサイトを表示するために使われていることを示しています。そして徐々に増加している傾向にあるのです。

別の理由は、最近のcookieのサイズはとても大きいので、画像やそれに類するリソースをcookieを使っていない別のホストに置くことです。cookieフリーな画像ホストを使うと、小さいHTTPリクエストをつかって性能を向上させることができる場合があります。

下図はスウェーデンのトップwebサイトの一つをブラウジングしたとき、パケットのトレースがどうなっているか、そしてどのようにリクエストが複数のホスト名に分散されているかを示しています。

expressen.seにおける画像のシャーディング