Skip to content

Instantly share code, notes, and snippets.

@trevnorris
Created August 16, 2016 21:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save trevnorris/5ddda4b7bcc628cc81f14e62dc94ad65 to your computer and use it in GitHub Desktop.
Save trevnorris/5ddda4b7bcc628cc81f14e62dc94ad65 to your computer and use it in GitHub Desktop.
Benchmark testing parsing JSON data vs parsing a binary format from a Buffer
'use strict';
const print = process._rawDebug;
const ITER = 1e6;
const four_nulls = '\u0000\u0000\u0000\u0000';
// Mock object of only strings.
const test_obj = {
foobarbaz1: Math.random().toString(16).substr(2),
foobarbaz2: 'abcdefghijklmnop'.repeat(5),
foobarbaz3: 'qrstuvwxyz'.repeat(3),
foobarbaz4: 'bamboombing',
foobarbaz5: 'flipfloop'.repeat(6),
foobarbaz6: 'aslkfdjsalfj'.repeat(4),
foobarbaz7: 'nananananananana BATMAN!'.repeat(10),
foobarbaz8: 'some crazy crew',
};
const test_buf = Buffer(JSON.stringify(test_obj));
const bin_data = genBinData(test_obj);
print('byte length:', test_buf.byteLength);
//print(new GenObjFromBin(bin_data));
//return;
var t = process.hrtime();
for (var i = 0; i < ITER; i++) {
// HERE: Comment out one or the other to run the benchmark.
//JSON.parse(test_buf);
//new GenObjFromBin(bin_data);
//JSON.stringify(test_obj);
genBinData(test_obj);
}
printTime(process.hrtime(t));
function printTime(t) {
const ns = t[0] * 1e9 + t[1];
print((ns / ITER).toFixed(2) + ' ns/op');
}
/*
* Structure of the data in the Buffer:
*
* ┌────────┬─────────────┬────────┬─────────────┬─────┐
* │ uint32 │ string data │ uint32 │ string data │ ... │
* └────────┴─────────────┴────────┴─────────────┴─────┘
*
* Each uint32 is binary and must be read using buf.readUInt32LE(), and is the
* length of the string data. From this each string can be sliced off.
*/
function readFields(buf) {
const ret_array = [];
const buf_length = buf.length;
var offset = 0;
do {
const string_length = buf.readUInt32LE(offset);
ret_array.push(buf.toString('utf8', offset + 4, offset + 4 + string_length));
offset += 4 + string_length;
} while (offset < buf_length);
return ret_array;
}
// Constructor used to create the new instance containing all the fields.
function GenObjFromBin(bin) {
const obj_array = readFields(bin);
this.foobarbaz1 = obj_array[0];
this.foobarbaz2 = obj_array[1];
this.foobarbaz3 = obj_array[2];
this.foobarbaz4 = obj_array[3];
this.foobarbaz5 = obj_array[4];
this.foobarbaz6 = obj_array[5];
this.foobarbaz7 = obj_array[6];
this.foobarbaz8 = obj_array[7];
}
// Helper function to turn an object into the binary form recognized by
// readFields(). This assumes all fields in the structure are strings.
function genBinData(obj) {
const strings_array = [];
for (var item in obj) {
strings_array.push(obj[item]);
}
const b = Buffer(four_nulls + strings_array.join(four_nulls));
const indexes_array = [0];
var last_index = 0;
do {
const idx = b.indexOf(four_nulls, last_index + 4, 'binary');
if (idx === -1) break;
indexes_array.push(idx);
last_index = idx;
} while(true);
for (var i = 0; i < indexes_array.length; i++) {
const size = indexes_array.length - 1 === i ? b.length - indexes_array[i] - 4 : indexes_array[i + 1] - indexes_array[i] - 4;
b.writeUInt32LE(size, indexes_array[i]);
}
return b;
/*
const bufs_array = [];
const strings_array = [];
const lengths_array = [];
var lengths_total = 0;
for (var item in obj) {
const item_byte_length = Buffer.byteLength(obj[item]);
lengths_array.push(item_byte_length);
lengths_total += item_byte_length;
strings_array.push(obj[item]);
//const byte_length = Buffer.byteLength(obj[item]);
//const b = Buffer(byte_length + 4);
//b.writeUInt32LE(byte_length);
//b.write(obj[item], 4);
//bufs_array.push(b);
}
//return Buffer.concat(bufs_array);
const b = Buffer(lengths_total + lengths_array.length * 4);
var offset = 0;
var idx = 0;
const write_string = ' ' + strings_array.join(' ');
b.write(write_string);
for (var i = 0; i < lengths_array.length; i++) {
b.writeUInt32LE(lengths_array[i], offset);
offset += lengths_array[i] + 4;
}
return b;
*/
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment