fast-base64
Advanced tools
Comparing version 0.1.2 to 0.1.3
@@ -5,3 +5,3 @@ // wat/base64-simd.wat | ||
// wat/base64.wat | ||
var base64_default = "AGFzbQEAAAABCgJgAX8AYAJ/fwACEwEHaW1wb3J0cwZtZW1vcnkCAAADAwIAAQcfAgxiYXNlNjQyYnl0ZXMAAAxieXRlczJiYXNlNjQAAQqzBAKUAgEDfwNAIAMgAkEDai0AACIBQQRqIAFBwABLQcUAbGsgAUHgAEtBBmxrIAFBK0ZBD2xqIAFBL0ZBDGxqIAItAAAiAUEEaiABQcAAS0HFAGxrIAFB4ABLQQZsayABQStGQQ9saiABQS9GQQxsakESdCACQQFqLQAAIgFBBGogAUHAAEtBxQBsayABQeAAS0EGbGsgAUErRkEPbGogAUEvRkEMbGpBDHRyIAJBAmotAAAiAUEEaiABQcAAS0HFAGxrIAFB4ABLQQZsayABQStGQQ9saiABQS9GQQxsakEGdHJyIgFBEHY6AAAgA0EBaiABQQh2OgAAIANBAmogAToAACADQQNqIQMgAkEEaiICIABJDQALC5oCAQN/A0AgASADQQJqLQAAIAMtAABBEHQgA0EBai0AAEEIdHJyIgRBEnYiAkHBAGogAkEZS0EGbGogAkEzS0HLAGxrIAJBPkZBD2xrIAJBP0ZBDGxrOgAAIAFBAWogBEEMdkE/cSICQcEAaiACQRlLQQZsaiACQTNLQcsAbGsgAkE+RkEPbGsgAkE/RkEMbGs6AAAgAUECaiAEQQZ2QT9xIgJBwQBqIAJBGUtBBmxqIAJBM0tBywBsayACQT5GQQ9sayACQT9GQQxsazoAACABQQNqIARBP3EiAkHBAGogAkEZS0EGbGogAkEzS0HLAGxrIAJBPkZBD2xrIAJBP0ZBDGxrOgAAIAFBBGohASADQQNqIgMgAEkNAAsL"; | ||
var base64_default = ""; | ||
@@ -31,3 +31,3 @@ // wasm-tools.js | ||
console.log("falling back to version without experimental feature"); | ||
wasmCode = toBytesJs(fallback.base64); | ||
wasmCode = toBytesJs(fallback); | ||
return W.instantiate(wasmCode, importObject); | ||
@@ -34,0 +34,0 @@ }); |
{ | ||
"name": "fast-base64", | ||
"description": "Fastest possible base64 encoding/decoding using WebAssembly", | ||
"version": "0.1.2", | ||
"version": "0.1.3", | ||
"author": "gregor <gregor.mitscha-baude@gmx.at>", | ||
@@ -31,2 +31,6 @@ "license": "MIT", | ||
}, | ||
"./nano": { | ||
"import": "./base64-nano.js", | ||
"require": "./base64-nano.js" | ||
}, | ||
"./url": { | ||
@@ -56,3 +60,3 @@ "import": "./url.js", | ||
"scripts": { | ||
"build": "mkdir -p dist && node esbuild-wat.js base64-wasm.js > dist/base64-wasm.js", | ||
"build": "mkdir -p dist && node build-lib.js", | ||
"test": "npx chrode test-base64.js" | ||
@@ -64,3 +68,3 @@ }, | ||
"binaryen": "^101.0.0", | ||
"chrode": "^0.2.5", | ||
"chrode": "^0.2.7", | ||
"esbuild": "^0.12.15", | ||
@@ -67,0 +71,0 @@ "eslint": "^7.31.0", |
@@ -11,2 +11,3 @@ # fast-base64 | ||
- The fastest existing JS implementation is the one shipped in this package | ||
- The smallest existing implementation is also shipped in this package, because why not 😁 | ||
@@ -31,2 +32,3 @@ ```sh | ||
- `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 | ||
@@ -42,5 +44,7 @@ Example for using the pure JS version: | ||
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`. | ||
## Base64 URL | ||
To support base64url, we offer two tiny helper functions (the runtime overhead compared with base64 transcoding itself is negligible): | ||
To support base64url, we offer two tiny helper functions which have negligible runtime overhead compared with base64 transcoding itself: | ||
@@ -54,7 +58,15 @@ ```js | ||
## Wouldn't this be *even faster* with threading? | ||
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). | ||
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. | ||
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()`. | ||
## Curious about Base64? | ||
In making this package, I tried many different approaches for base64 encoding, including using the native `atob()` and `btoa()` functions and native dataURI functionality. You can find 4 alternative encoding and 3 decoding methods here: https://github.com/mitschabaude/fast-base64/blob/main/base64-alternative.js | ||
In making this package, I tried many different approaches for base64 encoding, including using the native `atob()` and `btoa()` functions and native data URL functionality. You can find 4 alternative encoding and 3 decoding methods here: [./base64-alternative.js](https://github.com/mitschabaude/fast-base64/blob/main/base64-alternative.js) | ||
Turns out that one of the fastest bytes to base64 implementations in JS uses the good old FileReader API! | ||
Turns out that one of the fastest bytes to base64 implementations in JS uses the FileReader API 😮 | ||
@@ -72,1 +84,11 @@ ```js | ||
``` | ||
Oh, and maybe you can decipher `fast-base64/nano`? | ||
```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}; | ||
``` | ||
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. |
30701
14
555
90