メイン

Firefox アーカイブ

2007年07月27日

分割してみる

論理演算2で現れた

・コード1

var x = 0;
for (var i = 0; i < 1000000; i++) {
    x += i;
}

の処理時間はFirefox(Fx)では1046(ここでは比率のみが焦点なので単位は考えない)でした.ちなみにIEでは141です(小さい方が速い).Fxはかなり分が悪いようです.

一見これ以上いじりようのない単純なコードをFxでどこまで速くできるのか少し詳しく考えてみます.前回見たように30bitを超えないようにxを二つの変数に分けてみましょう.

・コード2

/*
    [x[1]:x[0]] += [y[1]:y[0]]を求める.
    ここで[a:b]はa * (1<<30) + bを意味する(0 <= a, b < (1<<30)).
*/
function add(x, y)
{
    var t = x[0] += y[0];
    x[1] += y[1];
    if (t >= (1 << 30)) {
        x[0] -= 1 << 30;
        x[1]++;
    }
}
function test2()
{
    var x = new Array(2);
    var y = new Array(2);
    x[0] = x[1] = 0;
    y[0] = y[1] = 0;
    for (var i = 0; i < 1000000; i++) {
        y[0] = i;
        add(x, y);
    }
    document.write(" ax=[" + x[1] + ":" + x[0] + "]<br>");
    document.write("sum=" + ((x[1] * 1073741824) + x[0]) + "<br>");
}

関数add(x, y)は30bit進数加算を愚直に書き下したものです.
このコードの処理時間はFxでは1032でした.
コード1に比べてかなり複雑なのに実行時間はほぼ同じです.速くなる可能性がありそうです(IEでは3032とコードが増えた分遅くなってます).

さて,このループ内ではadd(x, y)のy[1]は常に0です.したがってそのコードを除去してみます.

・コード3

function add(x, y)
{
    var t = x[0] += y[0];
    if (t >= (1 << 30)) {
        x[0] -= 1 << 30;
        x[1]++;
    }
}

この処理時間は766となりました.3割ほど速くなっています.
ついでに関数をインライン展開してみましょう.

・コード4

function test()
{
    var xL, xH, yL, yH;
    xL = xH = yL = yH = 0;
    for (var i = 0; i < 1000000; i++) {
        yL = i;
        var t = xL += yL;
        if (t >= (1 << 30)) {
            xL -= 1 << 30;
            xH++;
        }
    }
    document.write("sum=" + ((xH * (1 << 30)) + xL) + "<br>");
}

処理時間は219.関数呼び出しはかなり重いことが分かりました.
更に無駄なyL = iの代入を止めてみます.

・コード5

function test()
{
    var xL, xH, yL, yH;
    xL = xH = yL = yH = 0;
    for (var i = 0; i < 1000000; i++) {
        var t = xL += i;
        if (t >= (1 << 30)) {
            xL -= 1 << 30;
            xH++;
        }
    }
    document.write("sum=" + ((xH * (1 << 30)) + xL) + "<br>");
}

なんと処理時間は172と6倍以上速くなりました.コード1におけるIEの141に匹敵する速度です.

もちろん上記のようにいつもうまくいくとは限りませんが,重たい計算をさせる場合には考慮する価値はあると思われます.

・まとめ
1) FirefoxはIEに比べて30bitを超える整数値の扱いが苦手である.場合によっては分割したほうがよいこともある.
2) 関数呼び出しは重たい.

About Firefox

ブログ「mitsunari@cybozu labs」のカテゴリ「Firefox」に投稿されたすべてのエントリーのアーカイブのページです。過去のものから新しいものへ順番に並んでいます。

他にも多くのエントリーがあります。メインページアーカイブページも見てください。