Skip to content

Commit f91c432

Browse files
committed
Also optimize reader with what we have learned
1 parent d83f799 commit f91c432

File tree

13 files changed

+342
-50
lines changed

13 files changed

+342
-50
lines changed

README.md

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ protobuf.js [![travis][travis-image]][travis-url] [![npm][npm-image]][npm-url] [
1212
[paypal-image]: https://img.shields.io/badge/paypal-donate-yellow.svg
1313
[paypal-url]: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=dcode%40dcode.io&item_name=%3C3%20protobuf.js
1414

15+
**Recommended read:** [Changes in protobuf.js 6.0](https://github.com/dcodeIO/protobuf.js/wiki/Changes-in-protobuf.js-6.0)
16+
1517
Features
1618
--------
17-
* Lightning fast through [runtime code generation](#performance)
19+
* Optimized [for performance](#performance)
1820
* Exhaustive [browser support](#compatibility)
1921
* Managed [TypeScript definitions](#usage-with-typescript)
2022
* Elaborate [API documentation](#documentation)
@@ -374,23 +376,23 @@ JSON.stringify to buffer x 174,440 ops/sec ±1.46% (87 runs sampled)
374376
375377
benchmarking decoding performance ...
376378
377-
Type.decode from buffer x 976,639 ops/sec ±0.81% (91 runs sampled)
378-
JSON.parse from string x 294,282 ops/sec ±0.69% (89 runs sampled)
379-
JSON.parse from buffer x 263,440 ops/sec ±0.84% (93 runs sampled)
379+
Type.decode from buffer x 1,127,271 ops/sec ±0.76% (90 runs sampled)
380+
JSON.parse from string x 295,445 ops/sec ±0.74% (92 runs sampled)
381+
JSON.parse from buffer x 265,703 ops/sec ±0.85% (92 runs sampled)
380382
381383
Type.decode from buffer was fastest
382-
JSON.parse from string was 69.8% slower
383-
JSON.parse from buffer was 73.0% slower
384+
JSON.parse from string was 73.8% slower
385+
JSON.parse from buffer was 76.4% slower
384386
385387
benchmarking combined performance ...
386388
387-
Type to/from buffer x 205,029 ops/sec ±1.59% (88 runs sampled)
388-
JSON to/from string x 127,198 ops/sec ±0.76% (91 runs sampled)
389-
JSON to/from buffer x 90,980 ops/sec ±0.77% (91 runs sampled)
389+
Type to/from buffer x 232,255 ops/sec ±0.99% (87 runs sampled)
390+
JSON to/from string x 125,555 ops/sec ±1.01% (91 runs sampled)
391+
JSON to/from buffer x 91,243 ops/sec ±0.83% (91 runs sampled)
390392
391393
Type to/from buffer was fastest
392-
JSON to/from string was 37.5% slower
393-
JSON to/from buffer was 55.3% slower
394+
JSON to/from string was 46.0% slower
395+
JSON to/from buffer was 60.7% slower
394396
```
395397

396398
Note that JSON is a native binding nowadays and as such is *really* fast. So, how can protobuf.js be faster?

bench/bench.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
},
1515
"outer" : {
1616
"bool" : [ true, false, false, true, false, false, true ],
17-
"double": 0.5
17+
"double": 204.8
1818
}
1919
},
2020
"float": 0.25

bench/bench.proto

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ message Test {
55
string string = 1;
66
uint32 uint32 = 2;
77
Inner inner = 3;
8-
float float = 4;
8+
float float = 4; // make sure to set something that's fair to JSON
99

1010
message Inner {
1111

@@ -34,5 +34,7 @@ message Test {
3434
message Outer {
3535

3636
repeated bool bool = 1;
37-
double double = 2;
37+
double double = 2; // make sure to set something that's fair to JSON
3838
}
39+
40+
// bytes cannot be used

bench/read.js

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
var protobuf = require("../src/index"),
2+
newSuite = require("./suite"),
3+
ieee754 = require("../lib/ieee754");
4+
5+
// This benchmark compares raw data type performance of Uint8Array and Buffer.
6+
7+
var data = [ 0xCD, 0xCC, 0xCC, 0x3D ]; // ~0.10000000149011612 LE
8+
9+
var array = new Uint8Array(data);
10+
var buffer = Buffer.from(data);
11+
12+
var f64 = new Float64Array(1);
13+
var f32 = new Float32Array(f64.buffer);
14+
var f8b = new Uint8Array(f64.buffer);
15+
16+
// raw float read speed
17+
newSuite("float")
18+
.add("ieee754 array", function() {
19+
ieee754.read(array, 0, false, 23, 4);
20+
})
21+
.add("ieee754 buffer", function() {
22+
ieee754.read(buffer, 0, false, 23, 4);
23+
})
24+
.add("f32 array", function() {
25+
var pos = 0;
26+
f8b[pos++] = array[0];
27+
f8b[pos++] = array[1];
28+
f8b[pos++] = array[2];
29+
f8b[pos ] = array[3];
30+
return f32[0];
31+
})
32+
.add("f32 buffer", function() {
33+
var pos = 0;
34+
f8b[pos++] = buffer[0];
35+
f8b[pos++] = buffer[1];
36+
f8b[pos++] = buffer[2];
37+
f8b[pos ] = buffer[3];
38+
return f32[0];
39+
})
40+
.add("readFloatLE buffer", function() {
41+
buffer.readFloatLE(0, true);
42+
})
43+
.run();
44+
45+
var data = [ 0x9A, 0x99, 0x99, 0x99, 0x99, 0x99, 0xB9, 0x3F ]; // 0.1 LE
46+
47+
var array = new Uint8Array(data);
48+
var buffer = Buffer.from(data);
49+
50+
// raw double read speed
51+
newSuite("double")
52+
.add("ieee754 array", function() {
53+
ieee754.read(array, 0, false, 52, 8);
54+
})
55+
.add("ieee754 buffer", function() {
56+
ieee754.read(buffer, 0, false, 52, 8);
57+
})
58+
.add("f64 array", function() {
59+
var pos = 0;
60+
f8b[pos++] = array[0];
61+
f8b[pos++] = array[1];
62+
f8b[pos++] = array[2];
63+
f8b[pos++] = array[3];
64+
f8b[pos++] = array[4];
65+
f8b[pos++] = array[5];
66+
f8b[pos++] = array[6];
67+
f8b[pos ] = array[7];
68+
return f64[0];
69+
})
70+
.add("f64 buffer", function() {
71+
var pos = 0;
72+
f8b[pos++] = buffer[0];
73+
f8b[pos++] = buffer[1];
74+
f8b[pos++] = buffer[2];
75+
f8b[pos++] = buffer[3];
76+
f8b[pos++] = buffer[4];
77+
f8b[pos++] = buffer[5];
78+
f8b[pos++] = buffer[6];
79+
f8b[pos ] = buffer[7];
80+
return f64[0];
81+
})
82+
.add("readDoubleLE buffer", function() {
83+
buffer.readDoubleLE(0, true);
84+
})
85+
.run();
86+
87+
function readString(bytes) {
88+
var len = bytes.length;
89+
if (len) {
90+
var out = new Array(len), p = 0, c = 0;
91+
while (p < len) {
92+
var c1 = bytes[p++];
93+
if (c1 < 128)
94+
out[c++] = c1;
95+
else if (c1 > 191 && c1 < 224)
96+
out[c++] = (c1 & 31) << 6 | bytes[p++] & 63;
97+
else if (c1 > 239 && c1 < 365) {
98+
var u = ((c1 & 7) << 18 | (bytes[p++] & 63) << 12 | (bytes[p++] & 63) << 6 | bytes[p++] & 63) - 0x10000;
99+
out[c++] = 0xD800 + (u >> 10);
100+
out[c++] = 0xDC00 + (u & 1023);
101+
} else
102+
out[c++] = (c1 & 15) << 12 | (bytes[p++] & 63) << 6 | bytes[p++] & 63;
103+
}
104+
return String.fromCharCode.apply(String, out.slice(0, c));
105+
}
106+
}
107+
108+
// raw string read speed
109+
[
110+
"Lorem ipsu",
111+
"Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore ipsum."
112+
].forEach(function(str) {
113+
114+
var buffer = Buffer.from(str, "utf8"),
115+
array = new Uint8Array(buffer.length);
116+
for (var i = 0; i < buffer.length; ++i)
117+
array[i] = buffer[i];
118+
119+
newSuite("string[" + str.length + "]")
120+
.add("readString array", function() {
121+
readString(array);
122+
})
123+
.add("readString buffer", function() {
124+
readString(buffer)
125+
})
126+
.add("toString buffer", function() {
127+
buffer.toString("utf8", 0, buffer.length);
128+
})
129+
.add("utf8Slice buffer", function() {
130+
buffer.utf8Slice(0, buffer.length);
131+
})
132+
.run();
133+
});

bench/write.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ var protobuf = require("../src/index"),
44

55
// This benchmark compares raw data type performance of Uint8Array and Buffer.
66

7-
/* var array = new Uint8Array(8);
7+
var array = new Uint8Array(8);
88
var buffer = new Buffer(8);
99

1010
// raw fixed32 write speed
@@ -119,7 +119,6 @@ newSuite("bytes")
119119
source.copy(buffer, 0);
120120
})
121121
.run();
122-
*/
123122

124123
function writeString(buf, pos, val) {
125124
for (var i = 0; i < val.length; ++i) {

0 commit comments

Comments
 (0)