TypedArrayを広範囲にわたって書き替える処理は、やりようによってはかなり速度差が出ます。buffer
(ArrayBuffer)を異なる型で扱う事ができるので、それをうまく利用します。例えば以下の処理では4byte周期で0,1,2,3
という風に埋めていきます。
for(let a=1<<10,b=11,c=256;b--;a+=a){
let A=new Uint8Array(a);
console.log("size:",a)
console.time("u8");
for(let b=c;b--;)for(let b=0;b<a;A[b++]=3)A[b++]=0,A[b++]=1,A[b++]=2;
console.timeEnd("u8");
console.time("u16");
for(let b=c;b--;)for(let b=a>>1,B=new Uint16Array(A.buffer);b;B[--b]=256)B[--b]=770;
console.timeEnd("u16");
console.time("u32");
for(let b=c;b--;)for(let b=a>>2,B=new Uint32Array(A.buffer);b;)B[--b]=0x3020100;
console.timeEnd("u32");
console.time("i64");
for(let b=c;b--;)for(let b=a>>3,B=new BigInt64Array(A.buffer);b;)B[--b]=216736831629295872n;
console.timeEnd("i64");
console.time("fill32");
for(let b=c;b--;)new Uint32Array(A.buffer).fill(0x3020100);
console.timeEnd("fill32");
console.time("fill64");
for(let b=c;b--;)new BigInt64Array(A.buffer).fill(216736831629295872n);
console.timeEnd("fill64");
}
chrome
size: 1024
u8: 15.756103515625 ms
u16: 8.26611328125 ms
u32: 2.8740234375 ms
u64: 1.693115234375 ms
fill32:0.287841796875 ms
fill64:0.276123046875 ms
size: 2048
u8: 13.2578125 ms
u16: 1.6630859375 ms
u32: 1.235107421875 ms
u64: 1.718017578125 ms
fill32:0.64990234375 ms
fill64:0.241943359375 ms
size: 4096
u8: 5.841064453125 ms
u16: 2.971923828125 ms
u32: 2.19189453125 ms
u64: 3.171142578125 ms
fill32:0.694091796875 ms
fill64:0.426025390625 ms
size: 8192
u8: 9.9951171875 ms
u16: 1.485107421875 ms
u32: 1.401123046875 ms
u64: 0.618896484375 ms
fill32:1.260009765625 ms
fill64:0.739990234375 ms
size: 16384
u8: 9.066162109375 ms
u16: 2.8330078125 ms
u32: 2.677978515625 ms
u64: 1.139892578125 ms
fill32:2.745849609375 ms
fill64:1.342041015625 ms
size: 32768
u8: 18.387939453125 ms
u16: 5.751953125 ms
u32: 6.375 ms
u64: 3.11279296875 ms
fill32:10.18994140625 ms
fill64:3.56494140625 ms
size: 65536
u8: 37.29296875 ms
u16: 12.9521484375 ms
u32: 10.837158203125 ms
u64: 5.221923828125 ms
fill32:9.908935546875 ms
fill64:6.93798828125 ms
size: 131072
u8: 87.426025390625 ms
u16: 29.883056640625 ms
u32: 22.83203125 ms
u64: 10.51611328125 ms
fill32:26.31787109375 ms
fill64:11.4521484375 ms
size: 262144
u8: 178.02099609375 ms
u16: 49.41796875 ms
u32: 42.694091796875 ms
u64: 17.972900390625 ms
fill32:46.0419921875 ms
fill64:22.5859375 ms
size: 524288
u8: 293.27490234375 ms
u16: 99.09716796875 ms
u32: 91.1240234375 ms
u64: 39.10986328125 ms
fill32:93.23193359375 ms
fill64:45.8310546875 ms
size: 1048576
u8: 636.72509765625 ms
u16: 212.462890625 ms
u32: 179.7421875 ms
u64: 79.802978515625 ms
fill32:158.869873046875 ms
fill64:90.60986328125 ms
FireFox
size: 1024
u8: 3ms
u16: 3ms
u32: 3ms
i64: 3ms
fill32: 4ms
fill64: 2ms
size: 2048
u8: 6ms
u16: 5ms
u32: 5ms
i64: 4ms
fill32: 5ms
fill64: 0ms
size: 4096
u8: 8ms
u16: 2ms
u32: 1ms
i64: 2ms
fill32: 4ms
fill64: 2ms
size: 8192
u8: 5ms
u16: 3ms
u32: 2ms
i64: 3ms
fill32: 6ms
fill64: 3ms
size: 16384
u8: 9ms
u16: 8ms
u32: 4ms
i64: 4ms
fill32: 11ms
fill64: 7ms
size: 32768
u8: 19ms
u16: 14ms
u32: 8ms
i64: 7ms
fill32: 27ms
fill64: 14ms
size: 65536
u8: 52ms
u16: 29ms
u32: 25ms
i64: 13ms
fill32: 56ms
fill64: 33ms
size: 131072
u8: 83ms
u16: 52ms
u32: 27ms
i64: 22ms
fill32: 109ms
fill64: 49ms
size: 262144
u8: 143ms
u16: 109ms
u32: 54ms
i64: 44ms
fill32: 252ms
fill64: 104ms
size: 524288
u8: 281ms
u16: 205ms
u32: 106ms
i64: 85ms
fill32: 407ms
fill64: 219ms
size: 1048576
u8: 588ms
u16: 406ms
u32: 211ms
i64: 169ms
fill32: 737ms
fill64: 386ms
御覧の通り1 byteずつで書き込むUint8Array
はぶっちぎりで遅いです。型幅が増えるにつれて高速になっていくような感じです。
驚くべきはfill
関数よりUint32ArrayやBigInt64Arrayをfor loopでぶん回す方が高速になる場合がある事です。DataView
でも似たような傾向あり。