JSON Parse vs Base64 to ArrayBuffer (v3)

Revision 3 of this benchmark created on


Setup

THREE = function() {};
  
  /**
   * @author bhouston / http://exocortex.com/
   * Original source from: 2013, April 22: https://github.com/niklasvh/base64-arraybuffer (MIT-LICENSED)
   */
  
  THREE.Base64 = function () {
  };
  
  THREE.Base64.base64String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  
  THREE.Base64.base64DecodeLookup = function() {
  
    var coreArrayBuffer = new ArrayBuffer( 256 );
    var base64DecodeLookupTable = new Uint8Array( coreArrayBuffer );
    for( var i = 0; i < THREE.Base64.base64String.length; i ++ ) {
      base64DecodeLookupTable[ THREE.Base64.base64String[ i ].charCodeAt( 0 ) ] = i;
    }
  
    return base64DecodeLookupTable;
  
  }();
  
  THREE.Base64.fromArrayBuffer = function (arraybuffer) {
    var bytes = new Uint8Array(arraybuffer),
      i, len = bytes.buffer.byteLength, base64 = "";
  
    for (i = 0; i < len; i+=3) {
      base64 += THREE.Base64.base64String[bytes[i] >> 2];
      base64 += THREE.Base64.base64String[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];
      base64 += THREE.Base64.base64String[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];
      base64 += THREE.Base64.base64String[bytes[i + 2] & 63];
    }
  
    if ((len % 3) === 2) {
      base64 = base64.substring(0, base64.length - 1) + "=";
    } else if (len % 3 === 1) {
      base64 = base64.substring(0, base64.length - 2) + "==";
    }
  
    return base64;
  };
  
  THREE.Base64.toArrayBuffer = function() {
  
    var base64DecodeLookup = THREE.Base64.base64DecodeLookup;
  
    return function(base64) {
  
      var bufferLength = base64.length * 0.75,
        len = base64.length, i, p = 0,
        encoded1, encoded2, encoded3, encoded4;
  
      if (base64[base64.length - 1] === "=") {
        bufferLength--;
        if (base64[base64.length - 2] === "=") {
          bufferLength--;
        }
      }
  
      var arraybuffer = new ArrayBuffer(bufferLength),
      bytes = new Uint8Array(arraybuffer);
  
      for (i = 0; i < len; i+=4) {
        encoded1 = base64DecodeLookup[base64.charCodeAt(i)];
        encoded2 = base64DecodeLookup[base64.charCodeAt(i+1)];
        encoded3 = base64DecodeLookup[base64.charCodeAt(i+2)];
        encoded4 = base64DecodeLookup[base64.charCodeAt(i+3)];
  
        bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
        bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
        bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
      }
  
      return arraybuffer;
    };
  
  }();
  
  THREE.Base64.toArrayOfFloats = function( base64 ) {
  
    var arrayBuffer = THREE.Base64.toArrayBuffer( base64 );
    var floatArray = new Float32Array( arrayBuffer );
  
    var arrayOfFloats = [];
    for( var i = 0, il = floatArray.length; i < il; i ++ ) {
      arrayOfFloats.push( floatArray[i] );
    }  
  
    return arrayOfFloats;
  
  };
  
  
  
  
  /*
  Copyright Vassilis Petroulias [DRDigit]
  
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
  
         http://www.apache.org/licenses/LICENSE-2.0
  
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
  */
  var B64 = {
      alphabet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',
      lookup: null,
      ie: /MSIE /.test(navigator.userAgent),
      ieo: /MSIE [67]/.test(navigator.userAgent),
      encode: function (s) {
          var buffer = B64.toUtf8(s),
              position = -1,
              len = buffer.length,
              nan1, nan2, enc = [, , , ];
          if (B64.ie) {
              var result = [];
              while (++position < len) {
                  nan1 = buffer[position + 1], nan2 = buffer[position + 2];
                  enc[0] = buffer[position] >> 2;
                  enc[1] = ((buffer[position] & 3) << 4) | (buffer[++position] >> 4);
                  if (isNaN(nan1)) enc[2] = enc[3] = 64;
                  else {
                      enc[2] = ((buffer[position] & 15) << 2) | (buffer[++position] >> 6);
                      enc[3] = (isNaN(nan2)) ? 64 : buffer[position] & 63;
                  }
                  result.push(B64.alphabet[enc[0]], B64.alphabet[enc[1]], B64.alphabet[enc[2]], B64.alphabet[enc[3]]);
              }
              return result.join('');
          } else {
              result = '';
              while (++position < len) {
                  nan1 = buffer[position + 1], nan2 = buffer[position + 2];
                  enc[0] = buffer[position] >> 2;
                  enc[1] = ((buffer[position] & 3) << 4) | (buffer[++position] >> 4);
                  if (isNaN(nan1)) enc[2] = enc[3] = 64;
                  else {
                      enc[2] = ((buffer[position] & 15) << 2) | (buffer[++position] >> 6);
                      enc[3] = (isNaN(nan2)) ? 64 : buffer[position] & 63;
                  }
                  result += B64.alphabet[enc[0]] + B64.alphabet[enc[1]] + B64.alphabet[enc[2]] + B64.alphabet[enc[3]];
              }
              return result;
          }
      },
      decode: function (s) {
          var buffer = B64.fromUtf8(s),
              position = 0,
              len = buffer.length;
          if (B64.ieo) {
              result = [];
              while (position < len) {
                  if (buffer[position] < 128) result.push(String.fromCharCode(buffer[position++]));
                  else if (buffer[position] > 191 && buffer[position] < 224) result.push(String.fromCharCode(((buffer[position++] & 31) << 6) | (buffer[position++] & 63)));
                  else result.push(String.fromCharCode(((buffer[position++] & 15) << 12) | ((buffer[position++] & 63) << 6) | (buffer[position++] & 63)));
              }
              return result.join('');
          } else {
              result = '';
              while (position < len) {
                  if (buffer[position] < 128) result += String.fromCharCode(buffer[position++]);
                  else if (buffer[position] > 191 && buffer[position] < 224) result += String.fromCharCode(((buffer[position++] & 31) << 6) | (buffer[position++] & 63));
                  else result += String.fromCharCode(((buffer[position++] & 15) << 12) | ((buffer[position++] & 63) << 6) | (buffer[position++] & 63));
              }
              return result;
          }
      },
      toUtf8: function (s) {
          var position = -1,
              len = s.length,
              chr, buffer = [];
          if (/^[\x00-\x7f]*$/.test(s)) while (++position < len)
          buffer.push(s.charCodeAt(position));
          else while (++position < len) {
              chr = s.charCodeAt(position);
              if (chr < 128) buffer.push(chr);
              else if (chr < 2048) buffer.push((chr >> 6) | 192, (chr & 63) | 128);
              else buffer.push((chr >> 12) | 224, ((chr >> 6) & 63) | 128, (chr & 63) | 128);
          }
          return buffer;
      },
      fromUtf8: function (s) {
          var position = -1,
              len, buffer = [],
              enc = [, , , ];
          if (!B64.lookup) {
              len = B64.alphabet.length;
              B64.lookup = {};
              while (++position < len)
              B64.lookup[B64.alphabet[position]] = position;
              position = -1;
          }
          len = s.length;
          while (position < len) {
              enc[0] = B64.lookup[s.charAt(++position)];
              enc[1] = B64.lookup[s.charAt(++position)];
              buffer.push((enc[0] << 2) | (enc[1] >> 4));
              enc[2] = B64.lookup[s.charAt(++position)];
              if (enc[2] == 64) break;
              buffer.push(((enc[1] & 15) << 4) | (enc[2] >> 2));
              enc[3] = B64.lookup[s.charAt(++position)];
              if (enc[3] == 64) break;
              buffer.push(((enc[2] & 3) << 6) | enc[3]);
          }
          return buffer;
      }
  };
  
  
  
  
  var array = []
  for (var i = 0; i < 10000; i++) {
    array.push(i * 0.8734 - 5000);
  }
  
  var arrayBuffer = new ArrayBuffer(array.length * 4);
  var floatBuffer = new Float32Array(arrayBuffer);
  for (var i = 0; i < array.length; i++) {
    floatBuffer[i] = array[i];
  }
  
  var bufferInBase64 = THREE.Base64.fromArrayBuffer(arrayBuffer);
  var bufferInJSON = JSON.stringify(array);

Test runner

Ready to run.

Testing in
TestOps/sec
JSON to array of floats
var fromJson = JSON.parse(bufferInJSON);
ready
Base64 to arraybuffer
var fromBase64 = THREE.Base64.toArrayBuffer(bufferInBase64);
ready
Base64 to array of floats
var fromBase64 = THREE.Base64.toArrayOfFloats(bufferInBase64);
ready
var fromBase64 = B64.decode(bufferInBase64);
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.