Skip to content

Commit 1f9e335

Browse files
committed
Add a benchmark for TypedArray with zero-copy extension
1 parent fbcd36b commit 1f9e335

File tree

1 file changed

+91
-15
lines changed

1 file changed

+91
-15
lines changed

benchmark/msgpack-benchmark.js

+91-15
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,65 @@
33
"use strict";
44
require("ts-node/register");
55
const Benchmark = require("benchmark");
6-
const fs = require("fs");
7-
const msgpack = require("../src");
6+
7+
const msgpackEncode = require("..").encode;
8+
const msgpackDecode = require("..").decode;
9+
const ExtensionCodec = require("..").ExtensionCodec;
10+
11+
const float32ArrayExtensionCodec = new ExtensionCodec();
12+
float32ArrayExtensionCodec.register({
13+
type: 0x01,
14+
encode: (object) => {
15+
if (object instanceof Float32Array) {
16+
return new Uint8Array(object.buffer, object.byteOffset, object.byteLength);
17+
}
18+
return null;
19+
},
20+
decode: (data) => {
21+
const copy = new Uint8Array(data.byteLength);
22+
copy.set(data);
23+
return new Float32Array(copy.buffer);
24+
},
25+
});
26+
27+
const float32ArrayZeroCopyExtensionCodec = new ExtensionCodec();
28+
float32ArrayZeroCopyExtensionCodec.register({
29+
type: 0x01,
30+
encode: (object) => {
31+
if (object instanceof Float32Array) {
32+
return (pos) => {
33+
const bpe = Float32Array.BYTES_PER_ELEMENT;
34+
const padding = 1 + ((bpe - ((pos + 1) % bpe)) % bpe);
35+
const data = new Uint8Array(object.buffer);
36+
const result = new Uint8Array(padding + data.length);
37+
result[0] = padding;
38+
result.set(data, padding);
39+
return result;
40+
};
41+
}
42+
return null;
43+
},
44+
decode: (data) => {
45+
const padding = data[0];
46+
const bpe = Float32Array.BYTES_PER_ELEMENT;
47+
const offset = data.byteOffset + padding;
48+
const length = data.byteLength - padding;
49+
return new Float32Array(data.buffer, offset, length / bpe);
50+
},
51+
});
852

953
const implementations = {
1054
"@msgpack/msgpack": {
11-
encode: require("..").encode,
12-
decode: require("..").decode,
55+
encode: msgpackEncode,
56+
decode: msgpackDecode,
57+
},
58+
"@msgpack/msgpack (Float32Array extension)": {
59+
encode: (data) => msgpackEncode(data, { extensionCodec: float32ArrayExtensionCodec }),
60+
decode: (data) => msgpackDecode(data, { extensionCodec: float32ArrayExtensionCodec }),
61+
},
62+
"@msgpack/msgpack (Float32Array with zero-copy extension)": {
63+
encode: (data) => msgpackEncode(data, { extensionCodec: float32ArrayZeroCopyExtensionCodec }),
64+
decode: (data) => msgpackDecode(data, { extensionCodec: float32ArrayZeroCopyExtensionCodec }),
1365
},
1466
"msgpack-lite": {
1567
encode: require("msgpack-lite").encode,
@@ -21,28 +73,52 @@ const implementations = {
2173
},
2274
};
2375

24-
// exactly the same as:
25-
// https://raw.githubusercontent.com/endel/msgpack-benchmark/master/sample-large.json
26-
const sampleFiles = ["./sample-large.json"];
76+
const samples = [
77+
{
78+
// exactly the same as:
79+
// https://raw.githubusercontent.com/endel/msgpack-benchmark/master/sample-large.json
80+
name: "./sample-large.json",
81+
data: require("./sample-large.json"),
82+
},
83+
{
84+
name: "Large array of numbers",
85+
data: [
86+
{
87+
position: new Array(1e3).fill(1.14),
88+
},
89+
],
90+
},
91+
{
92+
name: "Large Float32Array",
93+
data: [
94+
{
95+
position: new Float32Array(1e3).fill(1.14),
96+
},
97+
],
98+
},
99+
];
27100

28101
function validate(name, data, encoded) {
29-
if (JSON.stringify(data) !== JSON.stringify(implementations[name].decode(encoded))) {
30-
throw new Error("Bad implementation: " + name);
31-
}
102+
return JSON.stringify(data) === JSON.stringify(implementations[name].decode(encoded));
32103
}
33104

34-
for (const sampleFile of sampleFiles) {
35-
const data = require(sampleFile);
105+
for (const sample of samples) {
106+
const { name: sampleName, data } = sample;
36107
const encodeSuite = new Benchmark.Suite();
37108
const decodeSuite = new Benchmark.Suite();
38109

39110
console.log("");
40-
console.log("**" + sampleFile + ":** (" + JSON.stringify(data).length + " bytes in JSON)");
111+
console.log("**" + sampleName + ":** (" + JSON.stringify(data).length + " bytes in JSON)");
41112
console.log("");
42113

43114
for (const name of Object.keys(implementations)) {
44115
implementations[name].toDecode = implementations[name].encode(data);
45-
validate(name, data, implementations[name].toDecode);
116+
if (!validate(name, data, implementations[name].toDecode)) {
117+
console.log("```");
118+
console.log("Not supported by " + name);
119+
console.log("```");
120+
continue;
121+
}
46122
encodeSuite.add("(encode) " + name, () => {
47123
implementations[name].encode(data);
48124
});
@@ -60,7 +136,7 @@ for (const sampleFile of sampleFiles) {
60136

61137
console.log("");
62138

63-
decodeSuite.on("cycle", function(event) {
139+
decodeSuite.on("cycle", (event) => {
64140
console.log(String(event.target));
65141
});
66142

0 commit comments

Comments
 (0)