base64符号化/復号の高速化の続編。以下の4種類で試しやがっときました。果たして更なる高速化を達成できるのか?
- 入出力ともにTypedArray利用
- 入力はDataView、出力はTypedArray利用
- 入力はTypedArray、出力はDataView利用
- 入出力ともにDataView利用
ちなみに1は前回の実装。
//// base64 encode
//TypedArray + TypedArray
const b2a=A=>{
var a=62,b=0,c,z=A.length,B=new Uint8Array((z*4+2)/3),C=new Uint8Array(64);
for(C[a]=43;a;)C[--a]=a>51?a-4:a>25?a+71:a+65;
for(C[63]=47;a<z;B[b++]=C[63&c])c=A[a++]<<16|A[a++]<<8|A[a++],B[b++]=C[c>>18],B[b++]=C[63&c>>12],B[b++]=C[63&c>>6];
return new TextDecoder().decode(B)
},
//DataView + TypedArray
B2a=A=>{
var a=62,b=0,c,z=A.length,y=z-3,B=new Uint8Array((z*4+2)/3),C=new Uint8Array(64),D=new DataView(A.buffer||new Uint8Array(A).buffer);
for(C[a]=43;a;)C[--a]=a>51?a-4:a>25?a+71:a+65;
for(C[63]=47;a<y;a+=3)c=D.getUint32(a)>>8,B[b++]=C[c>>18],B[b++]=C[c>>12&63],B[b++]=C[c>>6&63],B[b++]=C[c&63];
for(;a<z;B[b++]=C[c&63])c=A[a++]<<16|A[a++]<<8|A[a++],B[b++]=C[c>>18],B[b++]=C[c>>12&63],B[b++]=C[c>>6&63];
return new TextDecoder().decode(B)
},
//TypedArray + DataView
b2A=A=>{
var a=62,b=0,c,z=A.length,y=z-3,B=new Uint8Array((z*4+2)/3),C=new Uint8Array(64),E=new DataView(B.buffer);
for(C[a]=43;a;)C[--a]=a>51?a-4:a>25?a+71:a+65;
for(C[63]=47;a<y;b+=4)c=A[a++]<<16|A[a++]<<8|A[a++],E.setUint32(b,C[c>>18]<<24|C[c>>12&63]<<16|C[c>>6&63]<<8|C[c&63]);
for(;a<z;B[b++]=C[c&63])c=A[a++]<<16|A[a++]<<8|A[a++],B[b++]=C[c>>18],B[b++]=C[c>>12&63],B[b++]=C[c>>6&63];
return new TextDecoder().decode(B)
},
//DataView + DataView
B2A=A=>{
var a=62,b=0,c,z=A.length,y=z-3,B=new Uint8Array((z*4+2)/3),C=new Uint8Array(64),D=new DataView(A.buffer||new Uint8Array(A).buffer),E=new DataView(B.buffer);
for(C[a]=43;a;)C[--a]=a>51?a-4:a>25?a+71:a+65;
for(C[63]=47;a<y;a+=3)c=D.getUint32(a)>>8,E.setUint32(b,C[c>>18]<<24|C[c>>12&63]<<16|C[c>>6&63]<<8|C[c&63]),b+=4;
for(;a<z;B[b++]=C[c&63])c=A[a++]<<16|A[a++]<<8|A[a++],B[b++]=C[c>>18],B[b++]=C[c>>12&63],B[b++]=C[c>>6&63];
return new TextDecoder().decode(B)
},
//////// base64 decode
//TypedArray + TypedArray
a2b=A=>{
if(typeof A=="string")A=new TextEncoder().encode(A.replace(/[^A-Za-z\d/+]/g,""));
var a=62,b=0,c,z=A.length,B=new Uint8Array((z+2>>>2)*3-"0021"[z&3]),C=new Uint8Array(123);
for(C[43]=a;C[--a>51?a-4:a>25?a+71:a+65]=a;);
for(C[47]=63;a<z;B[b++]=255&c)c=C[A[a++]]<<18|C[A[a++]]<<12|C[A[a++]]<<6|C[A[a++]],B[b++]=c>>16,B[b++]=255&c>>8;
return B
},
//DataView + TypedArray
A2b=A=>{
if(typeof A=="string")A=new TextEncoder().encode(A.replace(/[^A-Za-z\d/+]/g,""));
var a=62,b=0,c,z=A.length,y=z-4,B=new Uint8Array((z+2>>>2)*3-"0021"[z&3]),C=new Uint8Array(123),D=new DataView(A.buffer||new Uint8Array(A).buffer);
for(C[43]=a;C[--a>51?a-4:a>25?a+71:a+65]=a;);
for(C[47]=63;a<y;a+=4)c=D.getUint32(a),c=C[c>>>24]<<18|C[c>>16&255]<<12|C[c>>8&255]<<6|C[c&255],B[b++]=c>>16,B[b++]=255&c>>8,B[b++]=255&c;
for(;a<z;B[b++]=255&c)c=C[A[a++]]<<18|C[A[a++]]<<12|C[A[a++]]<<6|C[A[a++]],B[b++]=c>>16,B[b++]=255&c>>8;
return B
},
//TypedArray + DataView
a2B=A=>{
if(typeof A=="string")A=new TextEncoder().encode(A.replace(/[^A-Za-z\d/+]/g,""));
var a=62,b=0,c,z=A.length,y=z-4,B=new Uint8Array((z+2>>>2)*3-"0021"[z&3]),C=new Uint8Array(123),E=new DataView(B.buffer);
for(C[43]=a;C[--a>51?a-4:a>25?a+71:a+65]=a;);
for(C[47]=63;a<y;b+=3)E.setUint32(b,C[A[a++]]<<26|C[A[a++]]<<20|C[A[a++]]<<14|C[A[a++]]<<8);
for(;a<z;B[b++]=255&c)c=C[A[a++]]<<18|C[A[a++]]<<12|C[A[a++]]<<6|C[A[a++]],B[b++]=c>>16,B[b++]=255&c>>8;
return B
},
//DataView + DataView
A2B=A=>{
if(typeof A=="string")A=new TextEncoder().encode(A.replace(/[^A-Za-z\d/+]/g,""));
var a=62,b=0,c,z=A.length,y=z-4,B=new Uint8Array((z+2>>>2)*3-"0021"[z&3]),C=new Uint8Array(123),D=new DataView(A.buffer||new Uint8Array(A).buffer),E=new DataView(B.buffer);
for(C[43]=a;C[--a>51?a-4:a>25?a+71:a+65]=a;);
for(C[47]=63;a<y;a+=4)c=D.getUint32(a),E.setUint32(b,C[c>>>24]<<26|C[c>>16&255]<<20|C[c>>8&255]<<14|C[c&255]<<8),b+=3;
for(;a<z;B[b++]=255&c)c=C[A[a++]]<<18|C[A[a++]]<<12|C[A[a++]]<<6|C[A[a++]],B[b++]=c>>16,B[b++]=255&c>>8;
return B
};
64万文字分を100回ずつ計測しました。符号化では1と2がほぼ大体かなり概ね同程度、3がそれより約5%高速、4が約10%高速という感じです。
復号では1と2が同程度、3と4はそれより若干遅かったり速かったりします。
ちなみに今回の実装でbase64符号化はArrayかTypedArrayを受け付け、出力は文字列、base64復号は文字列かArrayかTypedArrayを受け付け、Uint8Array出力となります