« [.NET] ASP.NET を x86 用にビルドすると、 動作しない | トップページ | Windows 7 : 製品ソフト開発者から出た "その疑問" にズバリお答えします! (第1回) »

2009年10月 7日 (水)

IE8 の Lookahead Downloader のバグ

…といっても、 騒ぐほどの事も無いし、 セキュリティ絡みも無さそうなんですけど。 f(^^;
関連して、 IE8 が文字エンコーディングをどう扱っているかが少し書かれていて、 興味深いです。

EricLaw's IEInternals : Bugs in IE8's Lookahead Downloader
July 27, 2009

まず最初に、 深刻なバグじゃないと強調しています。

If your page encounters one of these two problems, typically:

  • The visitor will not notice any problems like script errors, etc
  • The visitor will have a slightly slower experience when rendering the page because the speculative requests all "miss"
  • Your IIS/Apache logs will note requests for non-existent or incorrect resources

つまり、 見てるほうは遅いと感じるくらい、 Web サーバー側では 404 が増えるくらいの影響だよ、 と。

バグは、 IE8 の "Lookahead Downloader" ( そのまま 「ルックアヘッド・ダウンローダー」 としておきます ) に関するものです。
ブラウザは、 コンテンツを受信して描画するために HTML をパース ( 解析 ) するわけですが、 IE8 は何段階かに分けてパースします。 詳しくは書かれていませんが、 どうやら、 まず予備的にざっとなめてみて、 HTML 中に埋め込まれている JavaScript や CSS などの URL を拾い出して、 本格的なパーズを始める前にそれらのダウンロードを始めてしまいます。 これを行うのがルックアヘッド・ダウンローダーで、 そのダウンロード処理を "speculative downloads" ( 投機的なダウンロード ) と呼びます。
※ きちんとパーズしてみたら、 ダウンロードしたファイルが実は不要だったと判明するかもしれません。 なので "speculative ( 投機的な ) と呼ぶそうです。

このルックアヘッド・ダウンローダーに、 次の 2つのバグが見つかりました。

◆ BASE バグ
base 要素の対象が、 その後最初に登場するリンクを持った要素だけと解釈されるようです。 それ以降の要素では、 base 要素が無視されてしまいます。
このバグによって、 ルックアヘッド・ダウンローダーは間違ったリソースを要求し、 Web サーバーには 404 が記録されます。 その後、 メインのパーサーがパースした結果として正しいリソースを要求しなおすので、 表示は正常にされます。

◆ Missing 4K バグ
メインのパーサーが、 パース中に文字エンコーディングの誤りに気付いたとき、 パーサーとルックアヘッド・ダウンローダーはリスタート ( 最初からやり直し ) します。
このとき、 投機的ダウンロードすべき url が、 バッファの 4KB 境界をまたいでいると、 8KB からの文字列と結合されてしまうのだそうです。 そして、 その正しいはずのない文字列を url として、 ルックアヘッド・ダウンローダーはリクエストをし、 Web サーバーには 404 が記録されます。 その後、 メインのパーサーが再びパースしなおした結果として正しいリソースを要求しなおすので、 表示は正常にされます。

なお、 リスタートすることになる要因のひとつとして、 meta 要素を使った

<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">

のような文字エンコーディング指定を挙げています。 HTTP レスポンスヘッダーの charset 指定 ( もし無ければ ANSI ) に従ってパースしてきたのに、 meta 要素まできた所で実は違う文字エンコーディングだったと分かった、 ので、 もう一度最初からそのエンコーディングでやり直すよ、 ということなのでしょう。
対策としては、 パースを始める前に文字エンコーディングが確定するようにしておけ、 つまり、 HTTP レスポンスヘッダーで

Content-Type: text/html; charset=utf-8

を返すようにしなさい、 と。

最後に、 次のノートが書いてあります。

Note that specification of the charset in the HTTP header results in improved performance in all browsers, because the browser's parsers need not restart parsing from the beginning upon encountering the character set declaration. Furthermore, using the HTTP header helps mitigate certain XSS attack vectors.

・ HTTP ヘッダーで charset を指定すれば、 すべてのブラウザでパフォーマンスが向上するよ。
・ おまけに、 HTTP ヘッダーに charset を指定するやりかたは、 ある種のクロスサイトスクリプティング攻撃を防ぐこともできるよ。

さて。 このバグの記事から、 IE8 は、 HTTP ヘッダーの charset に指定された文字エンコーディングを使って、 HTML の解析を始めているようだと分かります。 そして、 途中で META タグによる文字エンコーディング指定が出てきたら、 あらためて最初から仕切りなおすのだ、 と。
IE のメニュー設定で文字コードを自動判別させるようにしていたら、 どうなるんでしょうね。 私は、 ルックアヘッド・ダウンローダーが動き出すところまでは、 少なくとも同じなんじゃないかと予想します。 そうしないと、 常に表示が遅くなっちゃいますからね。 もしそうなら、 文字コードを自動判別させるときでも、 最初は HTTP ヘッダーの charset に指定された文字エンコーディングで (投機ダウンロードのための) パースを始めるのでしょう。


( 2009/10/07 追記 )
XML 名前空間の指定 ( xmlns 属性 ) があってもリスタートするそうです。
となると、 xhtml のページは全滅… orz
ただし、 Fiddler を使っていくつかのサイトを見てみましたが、 リスタートしたら必ず無駄なリクエストが飛ぶわけではないようです。 同じページでも、 無駄なリクエストが出たり出なかったりします。 これはおそらく、 投機的ダウンロードが実際に始まる前にリスタートが掛かれば無駄なリクエストは出ないということじゃないかと思います。

( 2009/10/16 追記 )
2つのうち、 BASE バグの方は、 今月の Windows Update で修正されたそうです。
MS09-054: Internet Explorer の累積的なセキュリティ更新プログラム ( KB974455 )」 に含まれている、 「KB973536: Internet Explorer 8 is slow to load a Web page that contains the BASE tag」 が該当のものだそうな。
※ ついでに、 Fiddler の姉妹(?) Meddler HTTP Traffic Generation tool の紹介もされてます。 f(^^;

|

« [.NET] ASP.NET を x86 用にビルドすると、 動作しない | トップページ | Windows 7 : 製品ソフト開発者から出た "その疑問" にズバリお答えします! (第1回) »

PC・インターネット」カテゴリの記事

プログラミング」カテゴリの記事

コメント

コメントを書く



(ウェブ上には掲載しません)


コメントは記事投稿者が公開するまで表示されません。



トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/209349/46417500

この記事へのトラックバック一覧です: IE8 の Lookahead Downloader のバグ:

« [.NET] ASP.NET を x86 用にビルドすると、 動作しない | トップページ | Windows 7 : 製品ソフト開発者から出た "その疑問" にズバリお答えします! (第1回) »