textContent を使うと Opera10.60 がどんどん重くなる

uupaa2010-07-02

追記

http://jsdo.it/uupaa/u0QX に最小化したコードを載せました

今回のケースでは、条件(1)と(2)を満たす場合に、どんどん重くなっていくようです。

function bench() {
    // (1) nodeList を関数内部で毎回取得している 
    var nodeList = document.getElementsByTagName("li");
        i = 0, iz = nodeList.length;

    for (; i < iz; ++i) {
        // (2) textContent に代入している
        nodeList[i].textContent = i;
    }
}

本文

原稿書きの資料用に、最新のブラウザでベンチマークを取得していたところ、Opera10.60 のスコアだけがどんどん悪くなる(遅くなる)ケースがあることに事に気が付きました。


条件を絞り込んでいったところ

  • Opera10.60 (Build 3445)で発生する(Opera10.50でも発生するような気がする)
  • node.textContent に値を代入すると発生する
  • ページを閉じるまで回復しない
  • 100%再現する

な感じでした。

再現するコードを jsdoit に上げました。

スクリプトの中身は、FizzBuzzの皮をかぶった ただのベンチマークですが、Opera10.60で動かすとみるみるスコアが悪化します。

    function FizzBuzz() {
        var nodeList = document.getElementById("list").
                                getElementsByTagName("li"),
            i = 0, iz = nodeList.length,
            node, fizz, buzz, text;

        for (; i < iz; ++i) {
            node = nodeList[i];

            node.style.backgroundColor = i % 2 ? "#eee" : "white";

            fizz = i % 3 ? "" : "Fizz";
            buzz = i % 5 ? "" : "Buzz";
            text = (fizz && buzz) ? (fizz + " " + buzz)
                                  : (fizz || buzz || i);

            node.textContent = text; // ここが問題らしい
        }
    }

まず、自分のベンチマークの取り方に問題がある可能性を疑い、別のテストも用意して色々試したりと、ざっと4時間程かけて色々と模索したのですが、どうもブラウザ側の問題のようですよ。

バグ報告してませんけど、Opera10.61 まだかな〜