├── .gitignore ├── package.json ├── README.md └── benchmark.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "benchmark", 3 | "description": "Benchmark various MsgPack & encoding libraries", 4 | "version": "0.0.1", 5 | "dependencies": { 6 | "msgpack-js": "0.3.0", 7 | "msgpack": "1.0.2", 8 | "msgpack5": "3.2.0", 9 | "pson": "2.0.0", 10 | "avsc": "3.0.2" 11 | }, 12 | "engines": { 13 | "iojs": "4.2.2" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git@github.com:mattheworiordan/js-encoding-benchmark.git" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Node.js binary and string encoding library benchmarks 2 | 3 | A simple benchmark test to measure the performance of the following Node.js modules vs JSON: 4 | 5 | * [msgpack5](https://www.npmjs.com/package/msgpack5) 6 | * [msgpack](https://www.npmjs.com/package/msgpack) 7 | * [msgpack-js](https://www.npmjs.com/package/msgpack-js) 8 | * [pson](https://www.npmjs.com/package/pson) 9 | * [avsc](https://www.npmjs.com/package/avsc) 10 | 11 | ## Results 12 | 13 | $ node benchmark.js 14 | 15 | no binary buffers msgpack.pack: 446.188ms 16 | no binary buffers msgpack.unpack: 347.430ms 17 | 18 | no binary buffers msgpack-js.encode: 675.531ms 19 | no binary buffers msgpack-js.decode: 298.495ms 20 | 21 | no binary buffers pson.encode: 1208.759ms 22 | no binary buffers pson.decode: 276.973ms 23 | 24 | no binary buffers avsc.toBuffer: 57.868ms // See [1]. 25 | no binary buffers avsc.fromBuffer: 20.666ms 26 | 27 | no binary buffers JSON.stringify: 93.410ms 28 | no binary buffers JSON.parse: 93.165ms 29 | 30 | no binary buffers msgpack5.encode: 22254.455ms 31 | no binary buffers msgpack5.decode: 12134.576ms 32 | 33 | --- 34 | 35 | with binary buffers msgpack.pack: 498.184ms 36 | with binary buffers msgpack.unpack: 541.152ms 37 | 38 | with binary buffers msgpack-js.encode: 878.312ms 39 | with binary buffers msgpack-js.decode: 420.872ms 40 | 41 | with binary buffers pson.encode: 1596.219ms 42 | with binary buffers pson.decode: 393.904ms 43 | 44 | with binary buffers avsc.toBuffer: 85.295ms 45 | with binary buffers avsc.fromBuffer: 75.181ms 46 | 47 | with binary buffers JSON.stringify: 5620.344ms // See [2]. 48 | with binary buffers JSON.parse: 788.695ms 49 | 50 | with binary buffers msgpack5.encode: 33868.102ms 51 | with binary buffers msgpack5.decode: 11560.702ms 52 | 53 | 54 | Notes: 55 | 56 | 1. `avsc` expects the data's structure to be defined upfront using an Avro 57 | schema. See [here](https://github.com/mtth/avsc#examples) for examples and 58 | more information. 59 | 2. JSON encoding binary buffers is not relevant as binary data should be 60 | encoded manually in another format. For completeness however, this has been 61 | left in. 62 | 63 | # About 64 | 65 | We ran this simple benchmark test whilst reviewing Node.js encoding options at [Ably Real-time Messaging](https://www.ably.io) 66 | -------------------------------------------------------------------------------- /benchmark.js: -------------------------------------------------------------------------------- 1 | var msgpack = require('msgpack'), 2 | msgpackJs = require('msgpack-js'), 3 | msgpack5 = require('msgpack5')(), 4 | PSON = require('pson'), 5 | pson = new PSON.StaticPair(), 6 | avsc = require('avsc') 7 | 8 | // Avro type declarations for avsc. 9 | var typeWithoutBytes = avsc.parse({ 10 | name: 'Record', 11 | type: 'record', 12 | fields: [ 13 | {name: 'abcdef', type: 'int'}, 14 | {name: 'qqq', type: 'int'}, 15 | {name: 'a19', type: {type: 'array', items: 'int'}}, 16 | ] 17 | }) 18 | var typeWithBytes = avsc.parse({ 19 | name: 'Record', 20 | type: 'record', 21 | fields: [ 22 | {name: 'abcdef', type: 'int'}, 23 | {name: 'qqq', type: 'int'}, 24 | {name: 'a19', type: {type: 'array', items: 'int'}}, 25 | {name: 'buf', type: {name: 'Buf', type: 'fixed', size: 256}} 26 | ] 27 | }) 28 | 29 | function benchmark(name, data) { 30 | var testCount = 1e5, 31 | packed 32 | 33 | console.time(`${name} msgpack.pack`) 34 | for (var i = 0; i < testCount; i++) 35 | msgpack.pack(data) 36 | console.timeEnd(`${name} msgpack.pack`) 37 | 38 | encoded = msgpack.pack(data) 39 | console.time(`${name} msgpack.unpack`) 40 | for (var i = 0; i < testCount; i++) 41 | msgpack.unpack(encoded) 42 | console.timeEnd(`${name} msgpack.unpack`) 43 | 44 | console.time(`${name} msgpack-js.encode`) 45 | for (var i = 0; i < testCount; i++) 46 | msgpackJs.encode(data) 47 | console.timeEnd(`${name} msgpack-js.encode`) 48 | 49 | encoded = msgpackJs.encode(data) 50 | console.time(`${name} msgpack-js.decode`) 51 | for (var i = 0; i < testCount; i++) 52 | msgpackJs.decode(encoded) 53 | console.timeEnd(`${name} msgpack-js.decode`) 54 | 55 | console.time(`${name} pson.encode`) 56 | for (var i = 0; i < testCount; i++) 57 | pson.encode(data) 58 | console.timeEnd(`${name} pson.encode`) 59 | 60 | encoded = pson.toBuffer(data) // encoded data results in a "Error: Truncated" 61 | console.time(`${name} pson.decode`) 62 | for (var i = 0; i < testCount; i++) 63 | pson.decode(encoded) 64 | console.timeEnd(`${name} pson.decode`) 65 | 66 | var type = data.buf ? typeWithBytes : typeWithoutBytes 67 | 68 | console.time(`${name} avsc.toBuffer`) 69 | for (var i = 0; i < testCount; i++) 70 | type.toBuffer(data) 71 | console.timeEnd(`${name} avsc.toBuffer`) 72 | 73 | encoded = type.toBuffer(data) 74 | console.time(`${name} avsc.fromBuffer`) 75 | for (var i = 0; i < testCount; i++) 76 | type.fromBuffer(encoded) 77 | console.timeEnd(`${name} avsc.fromBuffer`) 78 | 79 | console.time(`${name} JSON.stringify`) 80 | for (var i = 0; i < testCount; i++) 81 | JSON.stringify(data) 82 | console.timeEnd(`${name} JSON.stringify`) 83 | 84 | encoded = JSON.stringify(data) 85 | console.time(`${name} JSON.parse`) 86 | for (var i = 0; i < testCount; i++) 87 | JSON.parse(encoded) 88 | console.timeEnd(`${name} JSON.parse`) 89 | 90 | console.time(`${name} msgpack5.encode`) 91 | for (var i = 0; i < testCount; i++) 92 | msgpack5.encode(data) 93 | console.timeEnd(`${name} msgpack5.encode`) 94 | 95 | encoded = msgpack5.encode(data) 96 | console.time(`${name} msgpack5.decode`) 97 | for (var i = 0; i < testCount; i++) 98 | msgpack5.decode(encoded) 99 | console.timeEnd(`${name} msgpack5.decode`) 100 | } 101 | 102 | var dataWithBinary = { 'abcdef' : 1, 'qqq' : 13, 'a19' : [1, 2, 3, 4], buf: require('crypto').randomBytes(256) }, 103 | dataPlain = { 'abcdef' : 1, 'qqq' : 13, 'a19' : [1, 2, 3, 4] } 104 | 105 | benchmark('no binary buffers', dataPlain) 106 | benchmark('with binary buffers', dataWithBinary) 107 | --------------------------------------------------------------------------------