Skip to content

Commit

Permalink
fix!: increase encoding/decoding performance (#58)
Browse files Browse the repository at this point in the history
Switches the internal serialization/deserialization code to use the Reader/Writer from protobufjs as it's very fast and also the least interesting thing about this module.

```console
% node packages/protons-benchmark/dist/src/encode.js
pbjs x 1,067,457 ops/sec ±1.74% (83 runs sampled)
protons x 1,165,064 ops/sec ±2.78% (90 runs sampled)
protobufjs x 1,317,685 ops/sec ±2.73% (89 runs sampled)
Fastest is protobufjs
```

```console
% node packages/protons-benchmark/dist/src/decode.js
pbjs x 1,997,186 ops/sec ±0.87% (86 runs sampled)
protons x 1,490,204 ops/sec ±2.40% (90 runs sampled)
protobufjs x 1,809,549 ops/sec ±0.58% (88 runs sampled)
Fastest is pbjs
```

```console
 % node packages/protons-benchmark/dist/src/index.js 
pbjs x 11,307 ops/sec ±6.04% (86 runs sampled)
protons x 11,376 ops/sec ±2.33% (80 runs sampled)
protobufjs x 12,086 ops/sec ±1.84% (89 runs sampled)
Fastest is protobufjs,pbjs
```

```console
% node packages/protons-benchmark/dist/src/rpc.js
protons x 3,308,190 ops/sec ±0.57% (92 runs sampled)
protobufjs x 3,135,946 ops/sec ±2.14% (91 runs sampled)
Fastest is protons
```

BREAKING CHANGE: the exported types of `protons-runtime` have changed and protobuf encoders/decoders will need to be regenerated
  • Loading branch information
achingbrain authored Aug 10, 2022
1 parent dab81db commit 9987b97
Show file tree
Hide file tree
Showing 48 changed files with 7,429 additions and 832 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ node_modules
package-lock.json
yarn.lock
.clinic
coverage
4 changes: 1 addition & 3 deletions lerna.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
{
"lerna": "4.0.0",
"packages": [
"packages/*"
],
"useWorkspaces": true,
"version": "independent",
"command": {
"run": {
Expand Down
11 changes: 7 additions & 4 deletions packages/protons-benchmark/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@
"sourceType": "module"
},
"ignorePatterns": [
"src/protobufjs/*.ts"
"src/pbjs/*",
"src/protobufjs/*"
]
},
"scripts": {
Expand All @@ -67,12 +68,14 @@
"start": "node dist/src/index.js"
},
"dependencies": {
"@types/benchmark": "^2.1.1",
"aegir": "^37.0.5",
"benny": "^3.7.1",
"benchmark": "^2.1.4",
"pbjs": "^0.0.14",
"protobufjs": "^6.11.2",
"protobufjs": "^7.0.0",
"protons": "^4.0.0",
"protons-runtime": "^2.0.0"
"protons-runtime": "^2.0.0",
"uint8arrays": "^3.1.0"
},
"private": true
}
1 change: 1 addition & 0 deletions packages/protons-benchmark/src/bench.proto
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
syntax = "proto3";

message Foo {
optional uint32 baz = 1;
Expand Down
50 changes: 50 additions & 0 deletions packages/protons-benchmark/src/decode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/* eslint-disable no-console */

/*
$ node dist/src/index.js
$ npx playwright-test dist/src/index.js --runner benchmark
*/

import Benchmark from 'benchmark'
import { Test as ProtonsTest } from './protons/bench.js'
import { decodeTest as pbjsDecodeTest } from './pbjs/bench.js'
import { Test as ProtobufjsTest } from './protobufjs/bench.js'

const message = {
meh: {
lol: 'sdkljfoee',
b: {
tmp: {
baz: 2309292
}
}
},
hello: 3493822,
foo: 'derp derp derp',
payload: Uint8Array.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
}

const buf = ProtonsTest.encode(message).subarray()

new Benchmark.Suite()
.add('pbjs', () => {
pbjsDecodeTest(buf)
})
.add('protons', () => {
ProtonsTest.decode(buf)
})
.add('protobufjs', () => {
ProtobufjsTest.decode(buf)
})
.on('error', (err: Error) => {
console.error(err)
})
.on('cycle', (event: any) => {
console.info(String(event.target))
})
.on('complete', function () {
// @ts-expect-error types are wrong
console.info(`Fastest is ${this.filter('fastest').map('name')}`) // eslint-disable-line @typescript-eslint/restrict-template-expressions
})
// run async
.run({ async: true })
48 changes: 48 additions & 0 deletions packages/protons-benchmark/src/encode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/* eslint-disable no-console */

/*
$ node dist/src/index.js
$ npx playwright-test dist/src/index.js --runner benchmark
*/

import Benchmark from 'benchmark'
import { Test as ProtonsTest } from './protons/bench.js'
import { encodeTest as pbjsEncodeTest } from './pbjs/bench.js'
import { Test as ProtobufjsTest } from './protobufjs/bench.js'

const message = {
meh: {
lol: 'sdkljfoee',
b: {
tmp: {
baz: 2309292
}
}
},
hello: 3493822,
foo: 'derp derp derp',
payload: Uint8Array.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
}

new Benchmark.Suite()
.add('pbjs', () => {
pbjsEncodeTest(message)
})
.add('protons', () => {
ProtonsTest.encode(message)
})
.add('protobufjs', () => {
ProtobufjsTest.encode(message).finish()
})
.on('error', (err: Error) => {
console.error(err)
})
.on('cycle', (event: any) => {
console.info(String(event.target))
})
.on('complete', function () {
// @ts-expect-error types are wrong
console.info(`Fastest is ${this.filter('fastest').map('name')}`) // eslint-disable-line @typescript-eslint/restrict-template-expressions
})
// run async
.run({ async: true })
42 changes: 26 additions & 16 deletions packages/protons-benchmark/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
/* eslint-disable no-console */

import benny from 'benny'
/*
$ node dist/src/index.js
$ npx playwright-test dist/src/index.js --runner benchmark
*/

import Benchmark from 'benchmark'
import { expect } from 'aegir/chai'
import { Test as ProtonsTest } from './protons/bench.js'
import { encodeTest as pbjsEncodeTest, decodeTest as pbjsDecodeTest } from './pbjs/bench.js'
Expand Down Expand Up @@ -27,30 +33,34 @@ function expectDecodedCorrectly (result: any) {
expect(result).to.have.property('payload').that.equalBytes(message.payload)
}

void benny.suite(
'Encode/Decode',

benny.add('pbjs', () => {
new Benchmark.Suite()
.add('pbjs', () => {
const buf = pbjsEncodeTest(message)
const result = pbjsDecodeTest(buf)

expectDecodedCorrectly(result)
}),

benny.add('protons', () => {
})
.add('protons', () => {
const buf = ProtonsTest.encode(message)
const result = ProtonsTest.decode(buf)

expectDecodedCorrectly(result)
}),

benny.add('protobufjs', () => {
})
.add('protobufjs', () => {
const buf = ProtobufjsTest.encode(message).finish()
const result = ProtobufjsTest.decode(buf)

expectDecodedCorrectly(result)
}),

benny.cycle(),
benny.complete()
)
})
.on('error', (err: Error) => {
console.error(err)
})
.on('cycle', (event: any) => {
console.info(String(event.target))
})
.on('complete', function () {
// @ts-expect-error types are wrong
console.info(`Fastest is ${this.filter('fastest').map('name')}`) // eslint-disable-line @typescript-eslint/restrict-template-expressions
})
// run async
.run({ async: true })
Loading

0 comments on commit 9987b97

Please sign in to comment.