Skip to content

Commit ebd1b9c

Browse files
authored
Merge pull request #13 from msgpack/async-decoder
Introduce decodeAsync() for streaming decoding
2 parents 6c278c6 + 788f81f commit ebd1b9c

File tree

13 files changed

+589
-203
lines changed

13 files changed

+589
-203
lines changed

README.md

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { deepStrictEqual } from "assert";
1515
import { encode, decode } from "@msgpack/msgpack";
1616

1717
const object = {
18-
nullOrUndefined: null,
18+
nil: null,
1919
integer: 1,
2020
float: Math.PI,
2121
string: "Hello, world!",
@@ -39,6 +39,20 @@ This library is publised as [@msgpack/msgpack](https://www.npmjs.com/package/@ms
3939
npm install @msgpack/msgpack
4040
```
4141

42+
## Encode and Decode
43+
44+
### `encode(data: unknown, options?): Uint8Array`
45+
46+
It encodes `data` and returns a byte array as `Uint8Array`.
47+
48+
### `decode(buffer: ArrayLike<number> | Uint8Array, options?): unknown`
49+
50+
It decodes `buffer` in a byte buffer and returns decoded data as `uknown`.
51+
52+
### `decodeAsync(stream: AsyncIterable<ArrayLike<number> | Uint8Array>, options?): Promise<unknown>`
53+
54+
It decodes `stream` in an async iterable of byte arrays and returns decoded data as `uknown` wrapped in `Promise`. This function works asyncronously.
55+
4256
## Extension Types
4357

4458
To handle [MessagePack Extension Types](https://github.com/msgpack/msgpack/blob/master/spec.md#extension-types), this library provides `ExtensionCodec` class.
@@ -105,17 +119,17 @@ If you use this library in NodeJS, v10 or later is required.
105119

106120
## Benchmark
107121

108-
Benchmark on NodeJS/v12.1.0 (macOS 10.14.4):
122+
Benchmark on NodeJS/v12.1.0
109123

110124
operation | op | ms | op/s
111125
----------------------------------------------------------------- | ------: | ----: | ------:
112-
buf = Buffer.from(JSON.stringify(obj)); | 496800 | 5000 | 99360
113-
buf = JSON.stringify(obj); | 911800 | 5000 | 182360
114-
obj = JSON.parse(buf); | 350600 | 5000 | 70120
115-
buf = require("msgpack-lite").encode(obj); | 350900 | 5000 | 70180
116-
obj = require("msgpack-lite").decode(buf); | 270800 | 5000 | 54160
117-
buf = require("@msgpack/msgpack").encode(obj); | 576700 | 5000 | 115340
118-
obj = require("@msgpack/msgpack").decode(buf); | 340800 | 5001 | 68146
126+
buf = Buffer.from(JSON.stringify(obj)); | 493600 | 5000 | 98720
127+
buf = JSON.stringify(obj); | 959600 | 5000 | 191920
128+
obj = JSON.parse(buf); | 346100 | 5000 | 69220
129+
buf = require("msgpack-lite").encode(obj); | 358300 | 5000 | 71660
130+
obj = require("msgpack-lite").decode(buf); | 270400 | 5000 | 54080
131+
buf = require("@msgpack/msgpack").encode(obj); | 594300 | 5000 | 118860
132+
obj = require("@msgpack/msgpack").decode(buf); | 343100 | 5000 | 68620
119133

120134
## Distrubition
121135

benchmark/profile-decode.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,24 @@
1-
import { encode, decode } from "../src";
1+
import { encode, decode, decodeAsync } from "../src";
22

33
const data = require("./benchmark-from-msgpack-lite-data.json");
44
const encoded = encode(data);
55

6+
console.log("encoded size:", encoded.byteLength);
7+
68
console.time("decode #1");
79
for (let i = 0; i < 10000; i++) {
810
decode(encoded);
911
}
1012
console.timeEnd("decode #1");
1113

12-
console.time("decode #2");
13-
for (let i = 0; i < 10000; i++) {
14-
decode(encoded);
15-
}
16-
console.timeEnd("decode #2");
14+
(async () => {
15+
const buffers = async function*() {
16+
yield encoded;
17+
};
18+
19+
console.time("decodeAsync #1");
20+
for (let i = 0; i < 10000; i++) {
21+
await decodeAsync(buffers());
22+
}
23+
console.timeEnd("decodeAsync #1");
24+
})();

benchmark/sync-vs-async.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#!ts-node
2+
/* eslint-disable no-console */
3+
4+
import { encode, decode, decodeAsync } from "../src";
5+
import { writeFileSync, unlinkSync, readFileSync, createReadStream } from "fs";
6+
import { deepStrictEqual } from "assert";
7+
8+
(async () => {
9+
const data = [];
10+
for (let i = 0; i < 1000; i++) {
11+
const id = i + 1;
12+
data.push({
13+
id,
14+
score: Math.round(Math.random() * Number.MAX_SAFE_INTEGER),
15+
title: `Hello, world! #${id}`,
16+
content: `blah blah blah `.repeat(20).trim(),
17+
createdAt: new Date(),
18+
});
19+
}
20+
const encoded = encode(data);
21+
const file = "benchmark/tmp.msgpack";
22+
writeFileSync(file, encoded);
23+
process.on("exit", () => unlinkSync(file));
24+
console.log(`encoded size ${Math.round(encoded.byteLength / 1024)}KiB`);
25+
26+
deepStrictEqual(decode(readFileSync(file)), data);
27+
deepStrictEqual(await decodeAsync(createReadStream(file)), data);
28+
29+
// sync
30+
console.time("readFileSync |> decode");
31+
for (let i = 0; i < 100; i++) {
32+
decode(readFileSync(file));
33+
}
34+
console.timeEnd("readFileSync |> decode");
35+
36+
// async
37+
console.time("creteReadStream |> decodeAsync");
38+
for (let i = 0; i < 100; i++) {
39+
await decodeAsync(createReadStream(file));
40+
}
41+
console.timeEnd("creteReadStream |> decodeAsync");
42+
})();

0 commit comments

Comments
 (0)