1
0

JavaScript: base64 decode最適化もどき

Last updated at Posted at 2024-03-03

色々な実装でbase64文字列の復号速度を検証していきます。特に難しい事はせず、どの組み込み関数やObjectを利用するかの違いが焦点となります。返り値はUint8Arrayとします。

//復号関数群
let u8map=s=>{s=s.replace(/[^A-Za-z\d+/]/g,"");
	var a=62,b=0,c,d=s.length,A=new Uint8Array(123),B=new Uint8Array((d+2>>>2)*3-[0,0,2,1][d&3]);
	for(A[43]=a;A[--a>51?a-4:a>25?a+71:a+65]=a;);
	for(A[47]=63;a<d;B[b++]=c&255)c=A[s.charCodeAt(a++)]<<18|A[s.charCodeAt(a++)]<<12|A[s.charCodeAt(a++)]<<6|A[s.charCodeAt(a++)],B[b++]=c>>16,B[b++]=c>>8&255;
	return B
},hmap=s=>{s=s.replace(/[^A-Za-z\d+/]/g,"").split("");
	for(var a=62,b=0,c,d=s.length,A={"+":62,"/":63},B=new Uint8Array((d+2>>>2)*3-[0,0,2,1][d&3]);A[String.fromCharCode(--a>51?a-4:a>25?a+71:a+65)]=a;);
	for(;a<d;B[b++]=c&255)c=A[s[a++]]<<18|A[s[a++]]<<12|A[s[a++]]<<6|A[s[a++]],B[b++]=c>>16,B[b++]=c>>8&255;
	return B
},index=s=>{s=s.replace(/[^A-Za-z\d+/]/g,"");
	for(var a=62,b=0,c,d=s.length,A="+/",B=new Uint8Array((d+2>>>2)*3-[0,0,2,1][d&3]);a;)A=String.fromCharCode(--a>51?a-4:a>25?a+71:a+65)+A;
	for(s+="AA";a<d;B[b++]=c&255)c=A.indexOf(s[a++])<<18|A.indexOf(s[a++])<<12|A.indexOf(s[a++])<<6|A.indexOf(s[a++]),B[b++]=c>>16,B[b++]=c>>8&255;
	return B
},b2a=s=>{s=btoa(s);
	for(var a=s.length,B=new Uint8Array(a);a;)B[--a]=s.charCodeAt(a);
	return B
},
//復号対象
b64="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".repeat(1e4),
//検証用変数
round=100,f=a=>a.charCodeAt();
//実践
for(let fn of[u8map,hmap,index,b2a,a=>Uint8Array.from(btoa(a),f)]){
	let a=round,t=new Date;
	for(;a--;)fn(b64);
	console.log(new Date-t)
}

結果、最速を誇ったのがb2aだ(btoa + for loop)! さすが組み込み関数様だぜ!
それに続くのがu8map([A-Za-z0-9/+]Uint8Arrayで数値変換するC言語風の実装)。
栄光の3番手につけたのがhmapだ(昔ながらの連想配列を利用したもの)。
不名誉ある4番手はindex(indexOf連発で遅いに決まっている)。
そしてUint8Array.fromが断然ダントツぶっちぎり圧倒的桁違いにクソ遅い! しかし記述が簡単だから許してあげようぜ!(許さん)
ただし復号しようとするbase64文字列が極端に短い場合や長い場合は結果が変わってくるっぽい。長い程u8mapが優勢になり、ある時点から最速になる(Google Chromeの場合)

codegolf

encoder 162 bytes

<input type=file oninput="with(new FileReader)readAsBinaryString(files[0]),onload=b=>a.href=top.URL.createObjectURL(new Blob([btoa(result)]))"><a download id=a>DL

decoder 158 bytes

<input type=file oninput="files[0].text().then(b=>a.href=top.URL.createObjectURL(new Blob([Uint8Array.from(atob(b),b=>b.charCodeAt())])))"><a download id=a>DL

いずれもFile処理専用

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0