ES5 + TypedArray 環境において、Hash 生成関数のように、大量のデータをループで処理する場合は、TypedArray を使った変数の参照を作成することで、さらなる最適化を期待できる場合があります。
function Adler32(source, // @arg Uint8Array|String
hex, // @arg Boolean = false
seed) { // @arg Integer = 1 - seed
// @ret UINT32|HexString - 0x00000000 or "00000000"
// @desc http://en.wikipedia.org/wiki/Adler-32
seed = seed === undefined ? 1 : seed;
var MOD_ADLER = 65521;
var MAGIC_NUMBER = 5550;
var source_ = typeof source === "string" ? _toUint8Array(source) : source;
var a = seed & 0xffff;
var b = (seed >>> 16) & 0xffff;
var len = source_.length;
var i = 0;
while (len > 0) {
var tlen = len > MAGIC_NUMBER ? MAGIC_NUMBER : len;
len -= tlen;
do {
a += source_[i++];
b += a;
} while (--tlen);
a %= MOD_ADLER;
b %= MOD_ADLER;
}
var u32 = ((b << 16) | a) >>> 0;
return hex ? _toHexString(u32) : u32;
}上記のコードの a, b, len, i, tlen を Uint32Array を使った参照にすることで、変数を UINT32 として JIT に認識させ、より最適化を促す事ができます。
function Adler32_2(source, // @arg Uint8Array|String
hex, // @arg Boolean = false
seed) { // @arg Integer = 1 - seed
// @ret UINT32|HexString - 0x00000000 or "00000000"
// @desc http://en.wikipedia.org/wiki/Adler-32
seed = seed === undefined ? 1 : seed;
var source_ = typeof source === "string" ? _toUint8Array(source) : source;
// optimization
var u32 = new Uint32Array([
seed & 0xffff, // a
(seed >>> 16) & 0xffff, // b
source_.length, // len
0, // i
0, // tlen
65521, // MOD_ADLER
5550, // MAGIC_NUMBER
0 // pad (reserved)
]);
var a = u32[0];
var b = u32[1];
var len = u32[2];
var i = u32[3];
var tlen = u32[4];
var MOD_ADLER = u32[5];
var MAGIC_NUMBER = u32[6];
while (len > 0) {
tlen = len > MAGIC_NUMBER ? MAGIC_NUMBER : len;
len -= tlen;
do {
a += source_[i++];
b += a;
} while (--tlen);
a %= MOD_ADLER;
b %= MOD_ADLER;
}
var result = ((b << 16) | a) >>> 0; // to uint32
return hex ? _toHexString(result) : result;
}これらのベンチマークを取ると、以下のようになります。
Adler32の場合は 20〜25% ほど改善されたようです。
DataSize: 102400
Adler32: 2.059999998891726
Adler32(optim): 1.6369999793823808 // Adler32_2 のスコア