JSON compression (v11)

Revision 11 of this benchmark created on


Description

Checking different JSON compression libs and techniques

Preparation HTML

<script src="https://rawgit.com/creationix/msgpack-js-browser/master/msgpack.js">
</script>
<script src="https://rawgit.com/nmrugg/LZMA-JS/master/src/lzma.js"></script>
<script src="https://rawgit.com/nmrugg/LZMA-JS/master/src/lzma_worker.js"></script>
<script src="https://cdn.jsdelivr.net/jsonh/0.0.2/jsonh.min.js"></script>
<script src="https://rawgit.com/BonsaiDen/BiSON.js/master/lib/bison.js"></script>
<script src="https://rawgit.com/hiddentao/lzw-async/master/lzw-async.min.js"></script>
<script src="https://rawgit.com/sapienlab/jsonpack/master/main.js"></script>

Setup

var json = [{
      surname: 'Jones',
      age: 15,
      gender: 'Male',
      id: 1
    }, {
      age: 15,
      gender: 'Female',
      id: 2,
      surname: 'Adams'
    }, {
      age: 34,
      gender: 'Female',
      id: 3,
      firstname: 'Sally'
    }, {
      age: 22,
      gender: 'Male',
      location: 'London'
    }, {
      surname: 'Turley',
      age: 19,
      gender: 'Male',
      id: 8
    }, {
      age: 76,
      gender: 'Female',
      id: 2,
      surname: 'Tempest'
    }, {
      age: 34,
      gender: 'Female',
      id: 3,
      firstname: 'Sally'
    }, {
      age: 22,
      gender: 'Male',
      location: 'London'
    }];
    
    if (!window.abc) {
      window.abc = {};
    }
    
    // create a new object and turn data into set of keys and their references
    
    
    function pack(items) {
      var data = {
        k: [],
        d: []
      };
      data.d = process(items, data.k, set);
      return data;
    }
    
    // grab the references and return the key values
    
    
    function unpack(items) {
      return process(items.d, items.k, get);
    }
    
    // loop through a list and run a function on its keys and values
    
    
    function process(items, keys, func) {
      var list = [],
        obj = {};
      for (var i = 0; i < items.length; ++i) {
        obj = {};
        for (var item in items[i]) {
          obj[func(item, keys)] = func(items[i][item], keys);
        }
        list.push(obj);
      }
      return list;
    }
    
    // set a key and return its index
    
    
    function set(item, items) {
      for (var i = 0; i < items.length; ++i) {
        if (item == items[i]) {
          return i;
        }
      }
      items.push(item);
      return items.length - 1;
    }
    
    // get a key value by its index
    
    
    function get(item, items) {
      return items[parseInt(item, 10)];
    }
    
    
    //LZW Compression/Decompression for Strings
    var LZW = {
      compress: function(uncompressed) {
        "use strict";
        // Build the dictionary.
        var i,
          dictionary = {},
          c,
          wc,
          w = "",
          result = [],
          dictSize = 256;
        for (i = 0; i < 256; i += 1) {
          dictionary[String.fromCharCode(i)] = i;
        }
    
        for (i = 0; i < uncompressed.length; i += 1) {
          c = uncompressed.charAt(i);
          wc = w + c;
          //Do not use dictionary[wc] because javascript arrays 
          //will return values for array['pop'], array['push'] etc
          // if (dictionary[wc]) {
          if (dictionary.hasOwnProperty(wc)) {
            w = wc;
          } else {
            result.push(dictionary[w]);
            // Add wc to the dictionary.
            dictionary[wc] = dictSize++;
            w = String(c);
          }
        }
    
        // Output the code for w.
        if (w !== "") {
          result.push(dictionary[w]);
        }
        return result;
      },
    
    
      decompress: function(compressed) {
        "use strict";
        // Build the dictionary.
        var i,
          dictionary = [],
          w,
          result,
          k,
          entry = "",
          dictSize = 256;
        for (i = 0; i < 256; i += 1) {
          dictionary[i] = String.fromCharCode(i);
        }
    
        w = String.fromCharCode(compressed[0]);
        result = w;
        for (i = 1; i < compressed.length; i += 1) {
          k = compressed[i];
          if (dictionary[k]) {
            entry = dictionary[k];
          } else {
            if (k === dictSize) {
              entry = w + w.charAt(0);
            } else {
              return null;
            }
          }
    
          result += entry;
    
          // Add w+entry[0] to the dictionary.
          dictionary[dictSize++] = w + entry.charAt(0);
    
          w = entry;
        }
        return result;
      }
    };

Teardown


    window.abc[testname] = data;
  

Test runner

Ready to run.

Testing in
TestOps/sec
Kim's Method (1KB)
var testname = 'kim';
var data = pack(json);
ready
msgpack.js (7KB)
var testname = 'msgpack';
var data = msgpack.encode(json);
ready
LZMA.compress (51KB)
var testname = 'LZMA';
var data = LZMA.compress(JSON.stringify(json), 1);
ready
hpack.js (1KB)
var testname = 'hpack';
var data = JSONH.stringify(json);
ready
bison.js (2KB)
var testname = 'bison';
var data = BISON.encode(json)
ready
LZWAsync.compress (4KB)
// When the Async option is checked... the test cannot complete
var testname = 'LZWAsync';
var data = 'not complete';
LZWAsync.compress({
  input: JSON.stringify(json),
  output: function(output) {
    data = output;
  }
});
ready
LZW.compress (1KB)
var testname = 'LZW';
var data = LZW.compress(JSON.stringify(json));
ready
jsonpack
var testname = 'jsonpack';
var data = jsonpack.pack(json);
ready

Revisions

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