perf(fromArrayBuffer): use less memory for large buffers (#242)
diff --git a/src/common/base64.js b/src/common/base64.js
index 5c0b3f4..06c39ff 100644
--- a/src/common/base64.js
+++ b/src/common/base64.js
@@ -23,7 +23,7 @@
base64.fromArrayBuffer = function (arrayBuffer) {
var array = new Uint8Array(arrayBuffer);
- return uint8ToBase64(array);
+ return btoa(bytesToBinaryString(array));
};
base64.toArrayBuffer = function (str) {
@@ -36,46 +36,12 @@
return arrayBuffer;
};
-// ------------------------------------------------------------------------------
-
-/* This code is based on the performance tests at http://jsperf.com/b64tests
- * This 12-bit-at-a-time algorithm was the best performing version on all
- * platforms tested.
- */
-
-var b64_6bit = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
-var b64_12bit;
-
-var b64_12bitTable = function () {
- b64_12bit = [];
- for (var i = 0; i < 64; i++) {
- for (var j = 0; j < 64; j++) {
- b64_12bit[i * 64 + j] = b64_6bit[i] + b64_6bit[j];
- }
+function bytesToBinaryString (bytes) {
+ var CHUNK_SIZE = 1 << 15;
+ var string = '';
+ for (var i = 0; i < bytes.length; i += CHUNK_SIZE) {
+ var chunk = bytes.subarray(i, i + CHUNK_SIZE);
+ string += String.fromCharCode.apply(null, chunk);
}
- b64_12bitTable = function () { return b64_12bit; };
- return b64_12bit;
-};
-
-function uint8ToBase64 (rawData) {
- var numBytes = rawData.byteLength;
- var output = '';
- var segment;
- var table = b64_12bitTable();
- for (var i = 0; i < numBytes - 2; i += 3) {
- segment = (rawData[i] << 16) + (rawData[i + 1] << 8) + rawData[i + 2];
- output += table[segment >> 12];
- output += table[segment & 0xfff];
- }
- if (numBytes - i === 2) {
- segment = (rawData[i] << 16) + (rawData[i + 1] << 8);
- output += table[segment >> 12];
- output += b64_6bit[(segment & 0xfff) >> 6];
- output += '=';
- } else if (numBytes - i === 1) {
- segment = (rawData[i] << 16);
- output += table[segment >> 12];
- output += '==';
- }
- return output;
+ return string;
}
diff --git a/test/test.base64.js b/test/test.base64.js
index a326a5e..1f7e726 100644
--- a/test/test.base64.js
+++ b/test/test.base64.js
@@ -53,6 +53,14 @@
);
});
+ it('can base64 encode big files reasonably fast', function () {
+ var bytes = Uint8Array.from({ length: 1 << 24 }, (v, i) => i & 0xff);
+
+ var start = Date.now();
+ base64.fromArrayBuffer(bytes.buffer);
+ expect(Date.now() - start).toBeLessThan(1000);
+ });
+
it('Test#003 : can base64 encode an text string in an ArrayBuffer', function () {
var orig = 'Some Awesome Test This Is!';
var base64string = btoa(orig);