« sha1.js | メイン | 分割してみる »

論理演算2

高速化のために,いくつかの基本的演算のベンチマークを取っていて驚くのはFirefox(Fx)での結果です.

function test()
{
    var x;
    for (var i = 0; i < 1000000; i++) {
        x = 1 >> 1; // a
//        x = 1 >>> 1; // b
//        x = (-1) >> 1;  // c
//        x = (-1) >>> 1; // d
    }
}
abcd
IE110110110110
Fx7878125890

(注意) 1 >> 1をi >> 1や (-i) >> 1に変えてもほぼ同じ.

どれもほぼ一定のIEに比べてFxで(-1)>>>1がやたら遅いのはどうしてでしょうか.

FxのSTORE_INT()のコードを見ると

if (INT_FITS_IN_JSVAL(i)) {                                           \
    v_ = INT_TO_JSVAL(i);                                             \
} else {                                                                    \
    ok = js_NewDoubleValue(cx, (jsdouble)(i), &v_);              \
    if (!ok)                                                                 \
        goto out;                                                          \
}

となっています.

#INT_FITS_IN_JSVAL(j)は -230-1<=j<=230-1なら真のマクロ.

つまり,xの値がその範囲を超えるとdouble型に移行し,その値を保存するためにメモリ確保関数が呼び出されます.

これが他に比べて10倍以上遅い原因となっています.
同様に

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

もFxはIEに比べて8倍近く遅くなります.SHA-1の演算では
230 - 1 < x < 2 32の整数は大量に出てくるわけですからこのペナルティは無視できません.

sha1.jsなどでは32bit整数値を二つの数値型変数に分けて入れることでそれに対応しました.

コメントを投稿

(いままで、ここでコメントしたことがないときは、コメントを表示する前にこのブログのオーナーの承認が必要になることがあります。承認されるまではコメントは表示されません。そのときはしばらく待ってください。)