fast-base64
Advanced tools
Comparing version 0.1.3 to 0.1.4
@@ -12,3 +12,3 @@ // inline-worker:__inline-worker | ||
function Worker2() { | ||
return inlineWorker('function m(t){postMessage([-1,!0,Object.keys(t)]),addEventListener("message",async({data:[e,r,i]})=>{try{let l=await t[r](...i),o=d([l]);postMessage([e,!0,l],o)}catch(l){postMessage([e,!1,""+l])}})}function d(t){let e=[];for(let r of t)r instanceof ArrayBuffer||r instanceof MessagePort||globalThis.ImageBitmap&&r instanceof ImageBitmap||globalThis.OffscreenCanvas&&r instanceof OffscreenCanvas?e.push(r):ArrayBuffer.isView(r)&&r.buffer instanceof ArrayBuffer&&e.push(r.buffer);return e}m({toBytes:b,toBase64:g});var h=new TextEncoder,w=new TextDecoder;function b(t){t=t.replace(/=/g,"");let e=t.length,r=e%4,i=r&&r-1,l=(e>>2)*3+i,o=new Uint8Array(e+3);h.encodeInto(t+"===",o);for(let n=0,a=0;n<e;n+=4,a+=3){let s=(f[o[n]]<<18)+(f[o[n+1]]<<12)+(f[o[n+2]]<<6)+f[o[n+3]];o[a]=s>>16,o[a+1]=s>>8&255,o[a+2]=s&255}return new Uint8Array(o.buffer,0,l)}function g(t){let e=t.length,r=e%3,i=Math.floor(e/3)*4+(r&&r+1),l=Math.ceil(e/3)*4,o=new Uint8Array(l);for(let a=0,s=0;s<e;a+=4,s+=3){let c=(t[s]<<16)+(t[s+1]<<8)+(t[s+2]|0);o[a]=u[c>>18],o[a+1]=u[c>>12&63],o[a+2]=u[c>>6&63],o[a+3]=u[c&63]}let n=w.decode(new Uint8Array(o.buffer,0,i));return r===1&&(n+="=="),r===2&&(n+="="),n}var p="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",f=Object.fromEntries(Array.from(p).map((t,e)=>[t.charCodeAt(0),e]));f["=".charCodeAt(0)]=0;f["-".charCodeAt(0)]=62;f["_".charCodeAt(0)]=63;var u=Object.fromEntries(Array.from(p).map((t,e)=>[e,t.charCodeAt(0)]));\n'); | ||
return inlineWorker('function u(t){postMessage([-1,!0,Object.keys(t)]),addEventListener("message",async({data:[e,r,i]})=>{try{let l=await t[r](...i),o=h([l]);postMessage([e,!0,l],o)}catch(l){postMessage([e,!1,""+l])}})}function h(t){let e=[];for(let r of t)r instanceof ArrayBuffer||r instanceof MessagePort||globalThis.ImageBitmap&&r instanceof ImageBitmap||globalThis.OffscreenCanvas&&r instanceof OffscreenCanvas?e.push(r):ArrayBuffer.isView(r)&&r.buffer instanceof ArrayBuffer&&e.push(r.buffer);return e}var w=new TextEncoder,g=new TextDecoder;function p(t){t=t.replace(/=/g,"");let e=t.length,r=e%4,i=r&&r-1,l=(e>>2)*3+i,o=new Uint8Array(e+3);w.encodeInto(t+"===",o);for(let n=0,s=0;n<e;n+=4,s+=3){let a=(f[o[n]]<<18)+(f[o[n+1]]<<12)+(f[o[n+2]]<<6)+f[o[n+3]];o[s]=a>>16,o[s+1]=a>>8&255,o[s+2]=a&255}return new Uint8Array(o.buffer,0,l)}function d(t){let e=t.length,r=e%3,i=Math.floor(e/3)*4+(r&&r+1),l=Math.ceil(e/3)*4,o=new Uint8Array(l);for(let s=0,a=0;a<e;s+=4,a+=3){let c=(t[a]<<16)+(t[a+1]<<8)+(t[a+2]|0);o[s]=m[c>>18],o[s+1]=m[c>>12&63],o[s+2]=m[c>>6&63],o[s+3]=m[c&63]}let n=g.decode(new Uint8Array(o.buffer,0,i));return r===1&&(n+="=="),r===2&&(n+="="),n}var b="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",f=Object.fromEntries(Array.from(b).map((t,e)=>[t.charCodeAt(0),e]));f["=".charCodeAt(0)]=0;f["-".charCodeAt(0)]=62;f["_".charCodeAt(0)]=63;var m=Object.fromEntries(Array.from(b).map((t,e)=>[e,t.charCodeAt(0)]));u({toBytes:p,toBase64:d});\n'); | ||
} | ||
@@ -15,0 +15,0 @@ |
@@ -12,3 +12,3 @@ // inline-worker:__inline-worker | ||
function Worker2() { | ||
return inlineWorker('var u="AGFzbQEAAAABDAJgAn9/AGADf39/AAIVAQdpbXBvcnRzBm1lbW9yeQIDAIAIAwMCAAEHHwIMYmFzZTY0MmJ5dGVzAAAMYnl0ZXMyYmFzZTY0AAEKjgUCxQICAn8BeyAAIQIgACEDA0AgAv0ABAAhBCAEQQT9D/1uIARBwAD9D/0oQcUA/Q/9Tv1xIARB4AD9D/0oQQb9D/1O/XEgBEEr/Q/9I0EP/Q/9Tv1uIARBL/0P/SNBDP0P/U79biEEIAT9DD8AAAA/AAAAPwAAAD8AAAD9TkEC/asBIAT9DAAwAAAAMAAAADAAAAAwAAD9TkEM/a0B/VAgBP0MAA8AAAAPAAAADwAAAA8AAP1OQQT9qwEgBP0MAAA8AAAAPAAAADwAAAA8AP1OQQr9rQH9UP1QIAT9DAAAAwAAAAMAAAADAAAAAwD9TkEG/asBIAT9DAAAAD8AAAA/AAAAPwAAAD/9TkEI/a0B/VD9UP0MAAECBAUGCAkKDA0OEBAQEP0OIQQgAyAE/QsEACACQRBqIQIgA0EMaiEDIAIgAUkNAAsLxAICAn8BeyACIQMgACEEA0AgBP0ABAD9DAABAhADBAUQBgcIEAkKCxD9DiEFIAX9DPwAAAD8AAAA/AAAAPwAAAD9TkEC/a0BIAX9DAMAAAADAAAAAwAAAAMAAAD9TkEM/asBIAX9DADwAAAA8AAAAPAAAADwAAD9TkEE/a0B/VD9UCAF/QwADwAAAA8AAAAPAAAADwAA/U5BCv2rASAF/QwAAMAAAADAAAAAwAAAAMAA/U5BBv2tAf1Q/VAgBf0MAAA/AAAAPwAAAD8AAAA/AP1OQQj9qwH9UCEFIAVBwQD9D/1uIAVBGf0P/ShBBv0P/U79biAFQTP9D/0oQcsA/Q/9Tv1xIAVBPv0P/SNBD/0P/U79cSAFQT/9D/0jQQz9D/1O/XEhBSADIAX9CwQAIANBEGohAyAEQQxqIQQgBCABSQ0ACws=";var b="";var i=WebAssembly,w={},D={};function m(t,{fallback:r}){let e=Math.random().toString();return n=>Q(e,t,n,r)}async function Q(t,r,e={},n){let A=D[t];if(A===void 0||!d(e,A.importObject)){let s=w[t];if(s)A=s.then(a=>i.instantiate(a,e));else{let a=B(r),l=i.instantiate(a,e).catch(o=>{if(n===void 0)throw o;return console.error(o),console.log("falling back to version without experimental feature"),a=B(n),i.instantiate(a,e)});w[t]=l.then(o=>o.module),A=l.then(o=>o.instance)}A.importObject=e,D[t]=A}return(await A).exports}var U=new i.Memory({initial:1});function d(t,r){let e=Object.keys(t),n=e.length;for(let A=0;A<n;A++)if(!p(t[e[A]],r[e[A]]))return!1;return n===Object.keys(r).length}function p(t,r){if(t===r)return!0;let e=Object.keys(t),n=e.length;for(let A=0;A<n;A++)if(t[e[A]]!==r[e[A]])return!1;return n===Object.keys(r).length}var h="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",f=Object.fromEntries(Array.from(h).map((t,r)=>[t.charCodeAt(0),r]));f[61]=0;function B(t){t=t.replace(/=/g,"");let r=t.length,e=r%4,n=(r>>2)*3+(e&&e-1),A=new TextEncoder().encode(t+"===");for(let s=0,a=0;s<r;s+=4,a+=3){let l=(f[A[s]]<<18)+(f[A[s+1]]<<12)+(f[A[s+2]]<<6)+f[A[s+3]];A[a]=l>>16,A[a+1]=l>>8&255,A[a+2]=l&255}return new Uint8Array(A.buffer,0,n)}function y(t){postMessage([-1,!0,Object.keys(t)]),addEventListener("message",async({data:[r,e,n]})=>{try{let A=await t[e](...n),s=I([A]);postMessage([r,!0,A],s)}catch(A){postMessage([r,!1,""+A])}})}function I(t){let r=[];for(let e of t)e instanceof ArrayBuffer||e instanceof MessagePort||globalThis.ImageBitmap&&e instanceof ImageBitmap||globalThis.OffscreenCanvas&&e instanceof OffscreenCanvas?r.push(e):ArrayBuffer.isView(e)&&e.buffer instanceof ArrayBuffer&&r.push(e.buffer);return r}y({toBytes:M,toBase64:O});var P=new TextEncoder,T=new TextDecoder,g=m(u,{fallback:b});async function M(t,r,e){let n=e.length,A=n%4,s=A&&A-1,a=(n>>2)*3+s,{base642bytes:l}=await g({imports:{memory:t}}),o=new Uint8Array(t.buffer,r.byteOffset,n);o.set(P.encode(e)),l(o.byteOffset,o.byteOffset+n)}async function O(t,r){let e=r.byteLength-2,n=e%3,A=Math.floor(e/3)*4+(n&&n+1),s=e+2,a=Math.ceil(e/3)*4,{bytes2base64:l}=await g({imports:{memory:t}}),o=new Uint8Array(t.buffer,r.byteOffset,s);o[e]=0,o[e+1]=0,l(r.byteOffset,r.byteOffset+e,r.byteOffset+s);let E=new Uint8Array(t.buffer,r.byteOffset+s,A).slice(),c=T.decode(E);return n===1&&(c+="=="),n===2&&(c+="="),c}\n'); | ||
return inlineWorker('var u="AGFzbQEAAAABDAJgAn9/AGADf39/AAIVAQdpbXBvcnRzBm1lbW9yeQIDAIAIAwMCAAEHHwIMYmFzZTY0MmJ5dGVzAAAMYnl0ZXMyYmFzZTY0AAEKjgUCxQICAn8BeyAAIQIgACEDA0AgAv0ABAAhBCAEQQT9D/1uIARBwAD9D/0oQcUA/Q/9Tv1xIARB4AD9D/0oQQb9D/1O/XEgBEEr/Q/9I0EP/Q/9Tv1uIARBL/0P/SNBDP0P/U79biEEIAT9DD8AAAA/AAAAPwAAAD8AAAD9TkEC/asBIAT9DAAwAAAAMAAAADAAAAAwAAD9TkEM/a0B/VAgBP0MAA8AAAAPAAAADwAAAA8AAP1OQQT9qwEgBP0MAAA8AAAAPAAAADwAAAA8AP1OQQr9rQH9UP1QIAT9DAAAAwAAAAMAAAADAAAAAwD9TkEG/asBIAT9DAAAAD8AAAA/AAAAPwAAAD/9TkEI/a0B/VD9UP0MAAECBAUGCAkKDA0OEBAQEP0OIQQgAyAE/QsEACACQRBqIQIgA0EMaiEDIAIgAUkNAAsLxAICAn8BeyACIQMgACEEA0AgBP0ABAD9DAABAhADBAUQBgcIEAkKCxD9DiEFIAX9DPwAAAD8AAAA/AAAAPwAAAD9TkEC/a0BIAX9DAMAAAADAAAAAwAAAAMAAAD9TkEM/asBIAX9DADwAAAA8AAAAPAAAADwAAD9TkEE/a0B/VD9UCAF/QwADwAAAA8AAAAPAAAADwAA/U5BCv2rASAF/QwAAMAAAADAAAAAwAAAAMAA/U5BBv2tAf1Q/VAgBf0MAAA/AAAAPwAAAD8AAAA/AP1OQQj9qwH9UCEFIAVBwQD9D/1uIAVBGf0P/ShBBv0P/U79biAFQTP9D/0oQcsA/Q/9Tv1xIAVBPv0P/SNBD/0P/U79cSAFQT/9D/0jQQz9D/1O/XEhBSADIAX9CwQAIANBEGohAyAEQQxqIQQgBCABSQ0ACws=";var b="AGFzbQEAAAABDAJgAn9/AGADf39/AAITAQdpbXBvcnRzBm1lbW9yeQIAAAMDAgABBx8CDGJhc2U2NDJieXRlcwAADGJ5dGVzMmJhc2U2NAABCrcEApgCAQJ/IAAhAwNAIAMgAEEDai0AACICQQRqIAJBwABLQcUAbGsgAkHgAEtBBmxrIAJBK0ZBD2xqIAJBL0ZBDGxqIAAtAAAiAkEEaiACQcAAS0HFAGxrIAJB4ABLQQZsayACQStGQQ9saiACQS9GQQxsakESdCAAQQFqLQAAIgJBBGogAkHAAEtBxQBsayACQeAAS0EGbGsgAkErRkEPbGogAkEvRkEMbGpBDHRyIABBAmotAAAiAkEEaiACQcAAS0HFAGxrIAJB4ABLQQZsayACQStGQQ9saiACQS9GQQxsakEGdHJyIgJBEHY6AAAgA0EBaiACQQh2OgAAIANBAmogAjoAACADQQNqIQMgAEEEaiIAIAFJDQALC5oCAQJ/A0AgAiAAQQJqLQAAIAAtAABBEHQgAEEBai0AAEEIdHJyIgRBEnYiA0HBAGogA0EZS0EGbGogA0EzS0HLAGxrIANBPkZBD2xrIANBP0ZBDGxrOgAAIAJBAWogBEEMdkE/cSIDQcEAaiADQRlLQQZsaiADQTNLQcsAbGsgA0E+RkEPbGsgA0E/RkEMbGs6AAAgAkECaiAEQQZ2QT9xIgNBwQBqIANBGUtBBmxqIANBM0tBywBsayADQT5GQQ9sayADQT9GQQxsazoAACACQQNqIARBP3EiA0HBAGogA0EZS0EGbGogA0EzS0HLAGxrIANBPkZBD2xrIANBP0ZBDGxrOgAAIAJBBGohAiAAQQNqIgAgAUkNAAsL";var i=WebAssembly,m={},j={};function y(r,{fallback:n}){let e=Math.random().toString();return s=>w(e,r,s,n)}async function w(r,n,e={},s){let t=j[r];if(t===void 0||!O(e,t.importObject)){let l=m[r];if(l)t=l.then(A=>i.instantiate(A,e));else{let A=p(n),o=i.instantiate(A,e).catch(a=>{if(s===void 0)throw a;return console.warn(a),console.warn("falling back to version without experimental feature"),A=p(s),i.instantiate(A,e)});m[r]=o.then(a=>a.module),t=o.then(a=>a.instance)}t.importObject=e,j[r]=t}return(await t).exports}var L=new i.Memory({initial:1});function O(r,n){let e=Object.keys(r),s=e.length;for(let t=0;t<s;t++)if(!N(r[e[t]],n[e[t]]))return!1;return s===Object.keys(n).length}function N(r,n){if(r===n)return!0;let e=Object.keys(r),s=e.length;for(let t=0;t<s;t++)if(r[e[t]]!==n[e[t]])return!1;return s===Object.keys(n).length}var P="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",f=Object.fromEntries(Array.from(P).map((r,n)=>[r.charCodeAt(0),n]));f[61]=0;function p(r){r=r.replace(/=/g,"");let n=r.length,e=n%4,s=(n>>2)*3+(e&&e-1),t=new TextEncoder().encode(r+"===");for(let l=0,A=0;l<n;l+=4,A+=3){let o=(f[t[l]]<<18)+(f[t[l+1]]<<12)+(f[t[l+2]]<<6)+f[t[l+3]];t[A]=o>>16,t[A+1]=o>>8&255,t[A+2]=o&255}return new Uint8Array(t.buffer,0,s)}function d(r){postMessage([-1,!0,Object.keys(r)]),addEventListener("message",async({data:[n,e,s]})=>{try{let t=await r[e](...s),l=F([t]);postMessage([n,!0,t],l)}catch(t){postMessage([n,!1,""+t])}})}function F(r){let n=[];for(let e of r)e instanceof ArrayBuffer||e instanceof MessagePort||globalThis.ImageBitmap&&e instanceof ImageBitmap||globalThis.OffscreenCanvas&&e instanceof OffscreenCanvas?n.push(e):ArrayBuffer.isView(e)&&e.buffer instanceof ArrayBuffer&&n.push(e.buffer);return n}d({toBytes:T,toBase64:x});var K=new TextEncoder,v=new TextDecoder,k=y(u,{fallback:b});async function T(r,n,e){let s=e.length,{base642bytes:t}=await k({imports:{memory:r}}),l=new Uint8Array(r.buffer,n.byteOffset,s);l.set(K.encode(e)),t(l.byteOffset,l.byteOffset+s)}async function x(r,n){let e=n.byteLength-2,s=e%3,t=Math.floor(e/3)*4+(s&&s+1),l=e+2,{bytes2base64:A}=await k({imports:{memory:r}}),o=new Uint8Array(r.buffer,n.byteOffset,l);o[e]=0,o[e+1]=0,A(n.byteOffset,n.byteOffset+e,n.byteOffset+l);let a=new Uint8Array(r.buffer,n.byteOffset+l,t).slice(),c=v.decode(a);return s===1&&(c+="=="),s===2&&(c+="="),c}\n'); | ||
} | ||
@@ -15,0 +15,0 @@ |
@@ -5,3 +5,3 @@ // wat/base64-simd.wat | ||
// wat/base64.wat | ||
var base64_default = ""; | ||
var base64_default = "AGFzbQEAAAABDAJgAn9/AGADf39/AAITAQdpbXBvcnRzBm1lbW9yeQIAAAMDAgABBx8CDGJhc2U2NDJieXRlcwAADGJ5dGVzMmJhc2U2NAABCrcEApgCAQJ/IAAhAwNAIAMgAEEDai0AACICQQRqIAJBwABLQcUAbGsgAkHgAEtBBmxrIAJBK0ZBD2xqIAJBL0ZBDGxqIAAtAAAiAkEEaiACQcAAS0HFAGxrIAJB4ABLQQZsayACQStGQQ9saiACQS9GQQxsakESdCAAQQFqLQAAIgJBBGogAkHAAEtBxQBsayACQeAAS0EGbGsgAkErRkEPbGogAkEvRkEMbGpBDHRyIABBAmotAAAiAkEEaiACQcAAS0HFAGxrIAJB4ABLQQZsayACQStGQQ9saiACQS9GQQxsakEGdHJyIgJBEHY6AAAgA0EBaiACQQh2OgAAIANBAmogAjoAACADQQNqIQMgAEEEaiIAIAFJDQALC5oCAQJ/A0AgAiAAQQJqLQAAIAAtAABBEHQgAEEBai0AAEEIdHJyIgRBEnYiA0HBAGogA0EZS0EGbGogA0EzS0HLAGxrIANBPkZBD2xrIANBP0ZBDGxrOgAAIAJBAWogBEEMdkE/cSIDQcEAaiADQRlLQQZsaiADQTNLQcsAbGsgA0E+RkEPbGsgA0E/RkEMbGs6AAAgAkECaiAEQQZ2QT9xIgNBwQBqIANBGUtBBmxqIANBM0tBywBsayADQT5GQQ9sayADQT9GQQxsazoAACACQQNqIARBP3EiA0HBAGogA0EZS0EGbGogA0EzS0HLAGxrIANBPkZBD2xrIANBP0ZBDGxrOgAAIAJBBGohAiAAQQNqIgAgAUkNAAsL"; | ||
@@ -29,4 +29,4 @@ // wasm-tools.js | ||
throw err; | ||
console.error(err); | ||
console.log("falling back to version without experimental feature"); | ||
console.warn(err); | ||
console.warn("falling back to version without experimental feature"); | ||
wasmCode = toBytesJs(fallback); | ||
@@ -33,0 +33,0 @@ return W.instantiate(wasmCode, importObject); |
{ | ||
"name": "fast-base64", | ||
"description": "Fastest possible base64 encoding/decoding using WebAssembly", | ||
"version": "0.1.3", | ||
"version": "0.1.4", | ||
"author": "gregor <gregor.mitscha-baude@gmx.at>", | ||
@@ -14,3 +14,5 @@ "license": "MIT", | ||
"wasm", | ||
"fast" | ||
"simd", | ||
"fast", | ||
"deno" | ||
], | ||
@@ -21,20 +23,15 @@ "type": "module", | ||
".": { | ||
"import": "./dist/base64-wasm.js", | ||
"require": "./dist/base64-wasm.js" | ||
"import": "./dist/base64-wasm.js" | ||
}, | ||
"./small": { | ||
"import": "./base64-wasm-small.js", | ||
"require": "./base64-wasm-small.js" | ||
"import": "./base64-wasm-small.js" | ||
}, | ||
"./js": { | ||
"import": "./base64-js.js", | ||
"require": "./base64-js.js" | ||
"import": "./base64-js.js" | ||
}, | ||
"./nano": { | ||
"import": "./base64-nano.js", | ||
"require": "./base64-nano.js" | ||
"import": "./base64-nano.js" | ||
}, | ||
"./url": { | ||
"import": "./url.js", | ||
"require": "./url.js" | ||
"import": "./url.js" | ||
} | ||
@@ -70,2 +67,3 @@ }, | ||
"esbuild": "^0.12.15", | ||
"esbuild-plugin-wat": "^0.1.1", | ||
"eslint": "^7.31.0", | ||
@@ -72,0 +70,0 @@ "find-cache-dir": "^3.3.1", |
@@ -26,3 +26,3 @@ # fast-base64 | ||
We support three versions of the library that have different speed and size trade-offs | ||
We support four versions of the library that have different speed and size trade-offs. | ||
@@ -32,5 +32,5 @@ - `fast-base64`: The default is the fastest version, 1.9kB minzipped, **async** API | ||
- `fast-base64/js`: Fastest pure JS version, 600 bytes minzipped, **sync** API, 2-30x slower | ||
- `fast-base64/nano`: Smallest possible version, 147 bytes, **sync** API, 3-100x slower | ||
- `fast-base64/nano`: Smallest possible version, 147 bytes, **sync** API, no `node` support, 3-100x slower | ||
Example for using the pure JS version: | ||
The APIs are all equivalent, except that the latter two are synchronous. Example for using the fast JS version: | ||
@@ -44,7 +44,7 @@ ```js | ||
DISCLAIMER: You probably don't *need* speed-optimized base64. `fast-base64/nano`, even if it is the slowest of all versions that I tried, could even be the best choice for typical applications, because the speed difference will be simply not noticable if payloads are not huge. For example, on my laptop, 10kB of base64 decode in in 0.06ms with `fast-base64` and in 5ms with `fast-base64/nano`. | ||
DISCLAIMER: You probably don't _need_ speed-optimized base64. `fast-base64/nano`, the slowest of all versions that I tried, could even be the best choice for typical applications, because the speed difference will simply not be noticable if payloads are not huge. For example, on my laptop, 10kB of base64 decode in 0.06ms with `fast-base64` and in 5ms with `fast-base64/nano`. | ||
## Base64 URL | ||
To support base64url, we offer two tiny helper functions which have negligible runtime overhead compared with base64 transcoding itself: | ||
To support base64url, we offer two tiny helper functions. | ||
@@ -58,10 +58,12 @@ ```js | ||
## Wouldn't this be *even faster* with threading? | ||
The added runtime overhead when combining these with the fastest de-/encoder is about 2-4x, which should be fine for almost all circumstances. | ||
Sadly, no. This repository includes variants of both the WASM and pure JS transcoders with threads, where I distribute the workload between multiple Web Workers and join their results once all are complete. You can check out the code in [./base64-wasm-threads.js](https://github.com/mitschabaude/fast-base64/blob/main/base64-wasm-threads.js) and [./base64-js-threads.js](https://github.com/mitschabaude/fast-base64/blob/main/base64-js-threads.js). | ||
## Wouldn't this be _even faster_ with threading? | ||
These turn out to be not faster than the single-threaded versions, irrespective of the number of workers, except for very large payloads (> 1MB) in the pure JS versions where 3-4 workers can provide a speed-up of 1.5-2x. Especially the WASM versions with threads are clearly slower. They also come with a larger bundle size and worse browser support. | ||
Sadly, no. This repository includes threaded variants of both the Wasm and pure JS encoding/decoding, where I distribute the workload between multiple Web Workers and join their results once all are complete. You can check out the code in [./base64-wasm-threads.js](https://github.com/mitschabaude/fast-base64/blob/main/base64-wasm-threads.js) and [./base64-js-threads.js](https://github.com/mitschabaude/fast-base64/blob/main/base64-js-threads.js). | ||
As far as I can tell, the added overhead of slicing up the input, messaging to the workers and back, and rejoining the results is bigger than the gains in performing the actual calculation. Base64 in Wasm is simply already faster than some Browser-native functions that are involved, like `postMessage()`, `TextEncoder.encode()` and `Uint8Array.splice()`. | ||
These turn out to be not faster than the single-threaded versions, irrespective of the number of workers, except for very large payloads (> 1MB) in the pure JS version (where 3-4 workers can provide a speed-up of 1.5-2x). Especially the Wasm version with threads is clearly slower. It also comes with a larger bundle size and worse browser support. | ||
As far as I can tell, the added overhead of slicing up the input, messaging to the workers and back, and recombining the results is bigger than the gains in performing the actual calculation. Base64 in Wasm is simply already faster than some Browser-native functions that are involved, like `postMessage()`, `TextEncoder.encode()` and `Uint8Array.splice()`. | ||
## Curious about Base64? | ||
@@ -88,7 +90,7 @@ | ||
```js | ||
let y=s=>Uint8Array.from(atob(s),c=>c.charCodeAt(0)), | ||
a=b=>btoa([...b].map(x=>String.fromCharCode(x)).join("")); | ||
export{y as toBytes, a as toBase64}; | ||
let y = s => Uint8Array.from(atob(s), c => c.charCodeAt(0)), | ||
a = b => btoa([...b].map(x => String.fromCharCode(x)).join('')); | ||
export {y as toBytes, a as toBase64}; | ||
``` | ||
If you want to compare and possibly tune performance by yourself, try running `yarn build` and `npx chrodemon test-base64.js` in the cloned repo. |
32422
561
92
8