読者です 読者をやめる 読者になる 読者になる

IE8の『IE8標準準拠モード』のパフォーマンスがビックリするほど悪い

ここ1ヶ月ほど、IE8のみをターゲットとした業務Webアプリ開発のお仕事をしてるんだけど、IE8で異常にパフォーマンスが劣化する問題に遭遇した。

現象

  • よくありがちな「ヘッダ固定テーブル」
  • 1行目およびN列を固定→<table>を4分割
  • マウスオーバー行の背景色を変える
    • マウスオーバーはclassNameを書き換えることで実装
  • 表示件数は数百行程度

ざっくり言うとこんなようなものを実装したところ、マウスオーバーが実用にならないレベルでモッサリとしてしまった。ログを取ったりして状況を調べてみたところ、DOMアクセス自体にはまったく問題がないのだが、classNameを書き換えた際の再描画パフォーマンスが非常に悪いところまでわかった。

原因っぽいもの

「じゃあ何で再描画が遅いの?」ということについて色々調べたところ、IE8の『IE8標準準拠モード』のパフォーマンスに問題があるっぽいという情報を見つけた。

ブラウザはWindows IE8限定とします。
HTMLファイルのDOCTYPE宣言によって標準準拠/後方互換モードを切り替えられますが、
下記JavaScriptをそれぞれで走らせた場合、明らかに標準準拠モードが遅いです。

for (var i = 0; i < 10000; i++)
{
var t = document.createTextNode(i + ", ");
var o = document.createElement("div").appendChild(t);
document.getElementById("test").appendChild(o);
}

標準準拠モードと後方互換モードのJavaScriptのパフォーマンスに - JavaScript - 教えて!goo

これを見る限りではレンダリングだけではなく、JavaScript自体のパフォーマンスにも影響がでているようである。

検証コード

IE8で動作させてください。console.log()を使ってるのでF12で開発者ツールを表示させないとエラーが出るかも。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=8">
<script type="text/javascript">
window.onload = function () {
    var start = new Date().getTime();

    var buf = [],
        i = 10000;
    buf.push('<div><table>');
    while (i--) {
        buf.push('<tr onmouseover="mouseover(event, this)" onmouseout="mouseout(event, this)"><td>a</td><td>b</td><td>c</td></tr>');
    }
    buf.push('</table></div>');
    document.body.innerHTML = buf.join('');

    setTimeout(function () { console.log(new Date().getTime() - start); }, 0);
}
function mouseover(event, currentTarget) {
    (event.currentTarget || currentTarget).style.backgroundColor = 'red';
}
function mouseout(event, currentTarget) {
    (event.currentTarget || currentTarget).style.backgroundColor = '';
}
</script>
<style>
div { width:300px; height:300px; overflow:scroll; }
table { width: 500px; }
td { border: 1px solid black; }
</style>
</head>
<body>
</body>
</html>
実行時間(初期表示にかかる時間)
IE8標準準拠モード 2213[msec]
IE7標準準拠モード 1348[msec]
Quirksモード 1150[msec]

まとめ

検証コードではElement.style.backgroundColorで背景色を変えているが、私が実際に地雷を踏んだケースでは、「比較的煩雑なCSSを使っている」状態で「classNameのON/OFFで背景色を切り替えた」ところ、数百行程度でパフォーマンス問題が発生してしまっていた。検証コードでは『IE7標準準拠モード』でも比較的良いパフォーマンスが出ているのだが、私のケースではそれではダメで『Quirksモード』ではOKという状況である。
今回の検証コードではその点については深く調査していないのだが、どうやらCSS解釈自体も遅くなるようなので、パフォーマンスを気にするようなアプリを作る際に『Quirksモード』で作らざるを得ないようだ。