Skip to content
Ioannis Charalampidis edited this page Jun 11, 2018 · 16 revisions

In the javascript world there quite few binary encoding projects. The most widespread ones are the Binary-JSON (BSON) and MessagePack file formats. Even though they are not directly targeting Javascript applications, they are available as npm modules for both node.js and the browser.

For this performance tests we tested these technologies for a variety of data sets. It was surprising to see that JBB outperformed the other two both in file size and loading speed.

The encoding time of JBB is slower because of the way the bundles are created: Each one of it's four data streams are written into 4 individual files and then merged into the final bundle. In addition, JBB is not a streaming format, requiring some additional time to compile it's internal lookup tables.

Set-Up

For this performance tests we compared the following various binary encoders available on npm for javascript applications:

For the following data:

  1. Low-resolution Country Polygons (GeoJSON) (251K)
  2. High-resolution Country Polygons (GeoJSON) (673K)
  3. Randomly generated JSON, mostly with strings (961K)
  4. 50,000 times repeated instance of { 'abcdef' : 1, 'qqq' : 13, '19' : [1, 2, 3, 4] } (1.8M)
  5. 50,000 times repeated instance of { 'abcdef' : Math.random(), 'qqq' : 13, '19' : [Math.random(), Math.random(), Math.random(), Math.random()] } (5.9M)

Results

We compared the output file size and and loading time. The results are the following:

A. Encoding/Decoding Time

Data JSON BSON MsgPack JBB
Encode Decode Encode Decode Encode Decode Encode Decode
1 5.784ms 4.428ms 33.713ms 32.986ms 6.021ms 8.770ms 127.750ms 7.962ms
2 8.444ms 13.871ms 41.690ms 48.039ms 14.350ms 18.508ms 215.315ms 18.269ms
3 5.110ms 13.339ms 33.584ms 30.697ms 18.537ms 16.346ms 186.009ms 18.545ms
4 59.316ms 84.020ms 237.391ms 404.492ms 151.971ms 153.366ms 294.919ms 5.308ms
5 117.916ms 111.693ms 304.340ms 368.778ms 168.251ms 186.816ms 539.299ms 79.913ms

B. Encoded File Size

We also tested how well the file gets compressed, since GZip compression can be transparently applied on HTTP data. Each file was compressed at maximum GZip compression (-9).

Data JSON BSON MsgPack JBB
Raw GZip Raw GZip Raw GZip Raw GZip
1 251K 101K 349K 172K 214K 146K 110K 70K
2 588K 204K 534K 207K 361K 184K 157K 78K
3 752K 210K 801K 238K 667K 220K 523K 166K
4 1,806K 5.4K 3,407K 129K 977K 2.5K 104B 118B
5 6,023K 2,290K 4,384K 1,575K 2,930K 1,360K 1,074K 877K

C. Summary

  • JBB is about 70% faster than Binary-JSON (BSON) and about 30% faster than MsgPack on decoding speed, even with one negative test-case (#3).
  • JBB creates files that (even their compressed versions) are about 61% smaller than Binary-JSON (BSON) and about 55% smaller than MsgPack.

Reference Scripts

The following code snippets were used to measure the numbers above:

Loaders & Generators

For loading the sample JSON files:

var fs = require('fs');
var _data = JSON.parse(fs.readFileSync('data.json', 'utf8'));

For generating dataset 4:

var _data = [];
for (var i=0; i<50000; i++) {
  _data.push(
    { 'abcdef' : 1, 'qqq' : 13, '19' : [1, 2, 3, 4] }
  );
}

For generating dataset 5:

var _data = [];
for (var i=0; i<50000; i++) {
  _data.push(
    { 'abcdef' : Math.random(), 'qqq' : 13, '19' : [Math.random(),Math.random(),Math.random(),Math.random()] }
  );
}

Encoder & Decoder

For JSON:

// Write down JSON
console.time('Write JSON');
fs.writeFileSync('test-data.json', JSON.stringify(_data))
console.timeEnd('Write JSON');

// Read json
console.time('Read JSON');
_saved = JSON.parse(fs.readFileSync('test-data.json'));
console.timeEnd('Read JSON');

For BSON:

var bson = require("bson");
var BSON = new bson.BSONPure.BSON();

// Write down BSON 
console.time('Write BSON');
fs.writeFileSync('test-data.bson', BSON.serialize(_data, false, true, false) );
console.timeEnd('Write BSON');

// Read BSON
console.time('Read BSON');
_saved = BSON.deserialize(fs.readFileSync('test-data.bson'));
console.timeEnd('Read BSON');

For MsgPack:

var msgpack = require('msgpack');

// Write down MSGPACK 
console.time('Write MsgPack');
fs.writeFileSync('test-data.msgpack', msgpack.pack(_data) );
console.timeEnd('Write MsgPack');

// Read MSGPACK
console.time('Read MsgPack');
_saved = msgpack.unpack(fs.readFileSync('test-data.msgpack'));
console.timeEnd('Read MsgPack');

For JBB:

var JBBEncoder = require('jbb/encoder');
var JBBDecoder = require('jbb/decoder');

// Write down JBB
console.time('Write JBB');
var bundle = new JBBEncoder("test-data.jbb");
bundle.encode( _data, 'countries' );
bundle.close();
console.timeEnd('Write JBB');

// Read JBB
console.time('Read JBB');
var bundle = new JBBDecoder("./");
bundle.add('test-data.jbb');
bundle.load(function(err, db) {
  console.timeEnd('Read JBB');
});