json-as 1.0.0-beta.17 → 1.0.0-beta.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{CHANGELOG → CHANGELOG.md} +7 -1
- package/README.md +80 -66
- package/assembly/__benches__/abc.bench.ts +22 -0
- package/assembly/__benches__/large.bench.ts +174 -0
- package/assembly/__benches__/medium.bench.ts +46 -0
- package/assembly/__benches__/small.bench.ts +33 -0
- package/assembly/__benches__/vec3.bench.ts +73 -0
- package/assembly/__tests__/arbitrary.spec.ts +3 -3
- package/assembly/__tests__/array.spec.ts +5 -8
- package/assembly/__tests__/box.spec.ts +10 -20
- package/assembly/__tests__/custom.spec.ts +7 -6
- package/assembly/__tests__/date.spec.ts +4 -6
- package/assembly/__tests__/float.spec.ts +3 -3
- package/assembly/__tests__/lib/index.ts +4 -0
- package/assembly/__tests__/map.spec.ts +1 -1
- package/assembly/__tests__/misc.spec.ts +90 -0
- package/assembly/__tests__/raw.spec.ts +3 -3
- package/assembly/__tests__/struct.spec.ts +3 -6
- package/assembly/custom/bench.ts +9 -2
- package/assembly/deserialize/simple/array/struct.ts +2 -3
- package/assembly/deserialize/simple/array.ts +1 -1
- package/assembly/deserialize/simple/bool.ts +1 -1
- package/assembly/deserialize/simple/map.ts +3 -4
- package/assembly/deserialize/simple/object.ts +2 -3
- package/assembly/deserialize/simple/raw.ts +1 -1
- package/assembly/deserialize/simple/struct.ts +9 -5
- package/assembly/index.ts +14 -5
- package/assembly/serialize/simple/arbitrary.ts +1 -0
- package/assembly/serialize/simple/array.ts +1 -0
- package/assembly/serialize/simple/bool.ts +1 -0
- package/assembly/serialize/simple/date.ts +1 -0
- package/assembly/serialize/simple/float.ts +1 -0
- package/assembly/serialize/simple/integer.ts +2 -1
- package/assembly/serialize/simple/map.ts +1 -0
- package/assembly/serialize/simple/object.ts +4 -3
- package/assembly/serialize/simple/raw.ts +1 -0
- package/assembly/serialize/simple/string.ts +1 -0
- package/assembly/test.ts +63 -39
- package/bench/abc.bench.ts +20 -0
- package/bench/large.bench.ts +126 -0
- package/bench/medium.bench.ts +43 -0
- package/bench/small.bench.ts +30 -0
- package/bench/vec3.bench.ts +26 -0
- package/index.ts +1 -1
- package/{lib → modules}/as-bs.ts +4 -13
- package/package.json +5 -3
- package/run-bench.as.sh +15 -0
- package/run-bench.js.sh +12 -0
- package/run-tests.sh +1 -1
- package/transform/lib/index.js +25 -45
- package/transform/lib/index.js.map +1 -1
- package/transform/src/index.ts +31 -72
- package/assembly/__benches__/misc.bench.ts +0 -47
- package/assembly/__benches__/schemas.ts +0 -25
- package/assembly/__benches__/string.bench.ts +0 -23
- package/assembly/__benches__/struct.bench.ts +0 -21
- package/assembly/as-bs.d.ts +0 -53
- package/bench/schemas.ts +0 -5
- package/bench/string.bench.ts +0 -16
- package/bench.js +0 -85
- /package/bench/{bench.ts → lib/bench.ts} +0 -0
- /package/{lib → modules}/tsconfig.json +0 -0
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## 2025-03-06 - 1.0.0
|
|
4
|
+
|
|
5
|
+
- fix: object with an object as a value containing a rhs bracket or brace would exit early [3b33e94](https://github.com/JairusSW/json-as/commit/3b33e9414dc04779d22d65272863372fcd7af4a6)
|
|
6
|
+
- fix: objects containing properties with type Obj | null did not deserialize when using \_\_deserialize
|
|
7
|
+
- chore: clean up
|
|
8
|
+
|
|
3
9
|
## 2025-03-04 - 1.0.0-beta.17
|
|
4
10
|
|
|
5
11
|
- fix: forgot to build transform
|
|
@@ -132,4 +138,4 @@
|
|
|
132
138
|
- feat: reduce memory usage so that it is viable for low-memory environments
|
|
133
139
|
- feat: write to a central buffer and reduce memory overhead
|
|
134
140
|
- feat: rewrite the transform to properly resolve schemas and link them together
|
|
135
|
-
- feat: pre-allocate and compute the minimum size of a schema to avoid memory out of range errors
|
|
141
|
+
- feat: pre-allocate and compute the minimum size of a schema to avoid memory out of range errors
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
|
7
7
|
█████ ███████ ██████ ██ ████ ██ ██ ███████
|
|
8
8
|
</span>
|
|
9
|
-
AssemblyScript - v1.0.0-beta.
|
|
9
|
+
AssemblyScript - v1.0.0-beta.18
|
|
10
10
|
</pre>
|
|
11
11
|
</h5>
|
|
12
12
|
|
|
@@ -14,6 +14,22 @@
|
|
|
14
14
|
|
|
15
15
|
JSON is the de-facto serialization format of modern web applications, but its serialization and deserialization remain a significant performance bottleneck, especially at scale. Traditional parsing approaches are computationally expensive, adding unnecessary overhead to both clients and servers. This library is designed to mitigate this by leveraging SIMD acceleration and highly optimized transformations.
|
|
16
16
|
|
|
17
|
+
## 🚨 What's new in v1.0.0
|
|
18
|
+
|
|
19
|
+
🔹First release of `v1.0.0`
|
|
20
|
+
|
|
21
|
+
🔹Breaking changes to the way custom serializers/deserializers function (See Custom Serializers below)
|
|
22
|
+
|
|
23
|
+
🔹Major performance improvements and addition of SIMD
|
|
24
|
+
|
|
25
|
+
🔹Extremely low memory overhead compared to pre-1.x.x versions (great for serverless workloads)
|
|
26
|
+
|
|
27
|
+
🔹Fixes to many major issues and newly discovered bugs
|
|
28
|
+
|
|
29
|
+
🔹Full support for dynamic objects, arrays, and values
|
|
30
|
+
|
|
31
|
+
🔹Full support for `JSON.Raw` type everywhere
|
|
32
|
+
|
|
17
33
|
## 📚 Contents
|
|
18
34
|
|
|
19
35
|
- [Installation](#-installation)
|
|
@@ -31,7 +47,7 @@ JSON is the de-facto serialization format of modern web applications, but its se
|
|
|
31
47
|
## 💾 Installation
|
|
32
48
|
|
|
33
49
|
```bash
|
|
34
|
-
npm install json-as@1.0.0-beta.
|
|
50
|
+
npm install json-as@1.0.0-beta.18
|
|
35
51
|
```
|
|
36
52
|
|
|
37
53
|
Add the `--transform` to your `asc` command (e.g. in package.json)
|
|
@@ -42,7 +58,7 @@ Add the `--transform` to your `asc` command (e.g. in package.json)
|
|
|
42
58
|
|
|
43
59
|
Alternatively, add it to your `asconfig.json`
|
|
44
60
|
|
|
45
|
-
```
|
|
61
|
+
```typescripton
|
|
46
62
|
{
|
|
47
63
|
"options": {
|
|
48
64
|
"transform": ["json-as/transform"],
|
|
@@ -55,9 +71,10 @@ If you'd like to see the code that the transform generates, run with `JSON_DEBUG
|
|
|
55
71
|
|
|
56
72
|
## 🪄 Usage
|
|
57
73
|
|
|
58
|
-
```
|
|
74
|
+
```typescript
|
|
59
75
|
import { JSON } from "json-as";
|
|
60
76
|
|
|
77
|
+
|
|
61
78
|
@json
|
|
62
79
|
class Vec3 {
|
|
63
80
|
x: f32 = 0.0;
|
|
@@ -65,8 +82,10 @@ class Vec3 {
|
|
|
65
82
|
z: f32 = 0.0;
|
|
66
83
|
}
|
|
67
84
|
|
|
85
|
+
|
|
68
86
|
@json
|
|
69
87
|
class Player {
|
|
88
|
+
|
|
70
89
|
@alias("first name")
|
|
71
90
|
firstName!: string;
|
|
72
91
|
lastName!: string;
|
|
@@ -74,6 +93,7 @@ class Player {
|
|
|
74
93
|
// Drop in a code block, function, or expression that evaluates to a boolean
|
|
75
94
|
@omitif((self: Player) => self.age < 18)
|
|
76
95
|
age!: i32;
|
|
96
|
+
|
|
77
97
|
@omitnull()
|
|
78
98
|
pos!: Vec3 | null;
|
|
79
99
|
isVerified!: boolean;
|
|
@@ -87,9 +107,9 @@ const player: Player = {
|
|
|
87
107
|
pos: {
|
|
88
108
|
x: 3.4,
|
|
89
109
|
y: 1.2,
|
|
90
|
-
z: 8.3
|
|
110
|
+
z: 8.3,
|
|
91
111
|
},
|
|
92
|
-
isVerified: true
|
|
112
|
+
isVerified: true,
|
|
93
113
|
};
|
|
94
114
|
|
|
95
115
|
const serialized = JSON.stringify<Player>(player);
|
|
@@ -109,10 +129,12 @@ This library allows selective omission of fields during serialization using the
|
|
|
109
129
|
|
|
110
130
|
This decorator excludes a field from serialization entirely.
|
|
111
131
|
|
|
112
|
-
```
|
|
132
|
+
```typescript
|
|
133
|
+
|
|
113
134
|
@json
|
|
114
135
|
class Example {
|
|
115
136
|
name!: string;
|
|
137
|
+
|
|
116
138
|
@omit
|
|
117
139
|
secret!: string;
|
|
118
140
|
}
|
|
@@ -128,10 +150,12 @@ console.log(JSON.stringify(obj)); // { "name": "Visible" }
|
|
|
128
150
|
|
|
129
151
|
This decorator omits a field only if its value is null.
|
|
130
152
|
|
|
131
|
-
```
|
|
153
|
+
```typescript
|
|
154
|
+
|
|
132
155
|
@json
|
|
133
156
|
class Example {
|
|
134
157
|
name!: string;
|
|
158
|
+
|
|
135
159
|
@omitnull()
|
|
136
160
|
optionalField!: string | null;
|
|
137
161
|
}
|
|
@@ -141,14 +165,18 @@ obj.name = "Present";
|
|
|
141
165
|
obj.optionalField = null;
|
|
142
166
|
|
|
143
167
|
console.log(JSON.stringify(obj)); // { "name": "Present" }
|
|
168
|
+
```
|
|
144
169
|
|
|
145
|
-
|
|
170
|
+
**@omitif((self: this) => condition)**
|
|
146
171
|
|
|
147
172
|
This decorator omits a field based on a custom predicate function.
|
|
148
173
|
|
|
174
|
+
```typescript
|
|
175
|
+
|
|
149
176
|
@json
|
|
150
177
|
class Example {
|
|
151
178
|
name!: string;
|
|
179
|
+
|
|
152
180
|
@omitif((self: Example) => self.age < 18)
|
|
153
181
|
age!: number;
|
|
154
182
|
}
|
|
@@ -168,7 +196,8 @@ AssemblyScript doesn't support using nullable primitive types, so instead, json-
|
|
|
168
196
|
|
|
169
197
|
For example, this schema won't compile in AssemblyScript:
|
|
170
198
|
|
|
171
|
-
```
|
|
199
|
+
```typescript
|
|
200
|
+
|
|
172
201
|
@json
|
|
173
202
|
class Person {
|
|
174
203
|
name!: string;
|
|
@@ -178,7 +207,8 @@ class Person {
|
|
|
178
207
|
|
|
179
208
|
Instead, use `JSON.Box` to allow nullable primitives:
|
|
180
209
|
|
|
181
|
-
```
|
|
210
|
+
```typescript
|
|
211
|
+
|
|
182
212
|
@json
|
|
183
213
|
class Person {
|
|
184
214
|
name: string;
|
|
@@ -207,7 +237,7 @@ Here's a few examples:
|
|
|
207
237
|
|
|
208
238
|
When dealing with arrays that have multiple types within them, eg. `["string",true,null,["array"]]`, use `JSON.Value[]`
|
|
209
239
|
|
|
210
|
-
```
|
|
240
|
+
```typescript
|
|
211
241
|
const a1 = JSON.parse<JSON.Value[]>('["string",true,null,["array"]]');
|
|
212
242
|
console.log(JSON.stringify(a[0])); // "string"
|
|
213
243
|
console.log(JSON.stringify(a[1])); // true
|
|
@@ -219,14 +249,15 @@ console.log(JSON.stringify(a[3])); // ["array"]
|
|
|
219
249
|
|
|
220
250
|
When dealing with an object with an unknown structure, use the `JSON.Obj` type
|
|
221
251
|
|
|
222
|
-
```
|
|
252
|
+
```typescript
|
|
223
253
|
const o1 = JSON.parse<JSON.Obj>('{"a":3.14,"b":true,"c":[1,2,3],"d":{"x":1,"y":2,"z":3}}');
|
|
224
254
|
|
|
225
255
|
console.log(o1.keys().join(" ")); // a b c d
|
|
226
256
|
console.log(
|
|
227
|
-
o1
|
|
228
|
-
|
|
229
|
-
|
|
257
|
+
o1
|
|
258
|
+
.values()
|
|
259
|
+
.map<string>((v) => JSON.stringify(v))
|
|
260
|
+
.join(" "),
|
|
230
261
|
); // 3.14 true [1,2,3] {"x":1,"y":2,"z":3}
|
|
231
262
|
|
|
232
263
|
const y = o1.get("d").get<JSON.Obj>().get<i32>();
|
|
@@ -239,7 +270,8 @@ More often, objects will be completely statically typed except for one or two va
|
|
|
239
270
|
|
|
240
271
|
In such cases, `JSON.Value` can be used to handle fields that may hold different types at runtime.
|
|
241
272
|
|
|
242
|
-
```
|
|
273
|
+
```typescript
|
|
274
|
+
|
|
243
275
|
@json
|
|
244
276
|
class DynamicObj {
|
|
245
277
|
id: i32 = 0;
|
|
@@ -267,9 +299,9 @@ Sometimes its necessary to simply copy a string instead of serializing it.
|
|
|
267
299
|
|
|
268
300
|
For example, the following data would typically be serialized as:
|
|
269
301
|
|
|
270
|
-
```
|
|
302
|
+
```typescript
|
|
271
303
|
const m1 = new Map<string, string>();
|
|
272
|
-
m1.set(
|
|
304
|
+
m1.set("pos", '{"x":1.0,"y":2.0,"z":3.0}');
|
|
273
305
|
|
|
274
306
|
const a1 = JSON.stringify(m1);
|
|
275
307
|
console.log("a1: " + a1);
|
|
@@ -279,9 +311,9 @@ console.log("a1: " + a1);
|
|
|
279
311
|
|
|
280
312
|
If, instead, one wanted to insert Raw JSON into an existing schema/data structure, they could make use of the JSON.Raw type to do so:
|
|
281
313
|
|
|
282
|
-
```
|
|
314
|
+
```typescript
|
|
283
315
|
const m1 = new Map<string, JSON.Raw>();
|
|
284
|
-
m1.set(
|
|
316
|
+
m1.set("pos", new JSON.Raw('{"x":1.0,"y":2.0,"z":3.0}'));
|
|
285
317
|
|
|
286
318
|
const a1 = JSON.stringify(m1);
|
|
287
319
|
console.log("a1: " + a1);
|
|
@@ -295,7 +327,8 @@ This library supports custom serialization and deserialization methods, which ca
|
|
|
295
327
|
|
|
296
328
|
Here's an example of creating a custom data type called `Point` which serializes to `(x,y)`
|
|
297
329
|
|
|
298
|
-
```
|
|
330
|
+
```typescript
|
|
331
|
+
|
|
299
332
|
@json
|
|
300
333
|
class Point {
|
|
301
334
|
x: f64 = 0.0;
|
|
@@ -305,11 +338,13 @@ class Point {
|
|
|
305
338
|
this.y = y;
|
|
306
339
|
}
|
|
307
340
|
|
|
341
|
+
|
|
308
342
|
@serializer
|
|
309
343
|
serializer(self: Point): string {
|
|
310
344
|
return `(${self.x},${self.y})`;
|
|
311
345
|
}
|
|
312
346
|
|
|
347
|
+
|
|
313
348
|
@deserializer
|
|
314
349
|
deserializer(data: string): Point {
|
|
315
350
|
const dataSize = bytes(data);
|
|
@@ -319,10 +354,7 @@ class Point {
|
|
|
319
354
|
const x = data.slice(1, c);
|
|
320
355
|
const y = data.slice(c + 1, data.length - 1);
|
|
321
356
|
|
|
322
|
-
return new Point(
|
|
323
|
-
f64.parse(x),
|
|
324
|
-
f64.parse(y)
|
|
325
|
-
);
|
|
357
|
+
return new Point(f64.parse(x), f64.parse(y));
|
|
326
358
|
}
|
|
327
359
|
}
|
|
328
360
|
```
|
|
@@ -333,7 +365,7 @@ The deserializer function parses the string `(x,y)` back into a `Point` instance
|
|
|
333
365
|
|
|
334
366
|
These functions are then wrapped before being consumed by the json-as library:
|
|
335
367
|
|
|
336
|
-
```
|
|
368
|
+
```typescript
|
|
337
369
|
@inline __SERIALIZE_CUSTOM(ptr: usize): void {
|
|
338
370
|
const data = this.serializer(changetype<Point>(ptr));
|
|
339
371
|
const dataSize = data.length << 1;
|
|
@@ -352,45 +384,27 @@ This allows custom serialization while maintaining a generic interface for the l
|
|
|
352
384
|
|
|
353
385
|
The `json-as` library has been optimized to achieve near-gigabyte-per-second JSON processing speeds through SIMD acceleration and highly efficient transformations. Below are some key performance benchmarks to give you an idea of how it performs.
|
|
354
386
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
| Test Case
|
|
360
|
-
|
|
|
361
|
-
| Vector3 Object
|
|
362
|
-
| Alphabet String
|
|
363
|
-
| Small
|
|
364
|
-
| Medium
|
|
365
|
-
| Large
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
| Test Case
|
|
370
|
-
|
|
|
371
|
-
| Vector3 Object
|
|
372
|
-
| Alphabet String
|
|
373
|
-
| Small
|
|
374
|
-
| Medium
|
|
375
|
-
| Large
|
|
376
|
-
|
|
377
|
-
JavaScript
|
|
378
|
-
|
|
379
|
-
| Test Case | Serialization (ops/s) | Deserialization (ops/s) | Serialization (MB/s) | Deserialization (MB/s) |
|
|
380
|
-
| ------------------ | --------------------- | ----------------------- | -------------------- | ---------------------- |
|
|
381
|
-
| Vector3 Object | 2,548,013 ops/s | 1,942,440 ops/s | 97 MB/s | 73 MB/s |
|
|
382
|
-
| Alphabet String | 3,221,556 ops/s | 2,716,617 ops/s | 624 MB/s | 537 MB/s |
|
|
383
|
-
| Small JSON Object | [Fill Value] | [Fill Value] | [Fill Value] | [Fill Value] |
|
|
384
|
-
| Medium JSON Object | [Fill Value] | [Fill Value] | [Fill Value] | [Fill Value] |
|
|
385
|
-
| Large JSON Object | [Fill Value] | [Fill Value] | [Fill Value] | [Fill Value] |
|
|
386
|
-
|
|
387
|
-
### Real-World Usage
|
|
388
|
-
|
|
389
|
-
| Scenario | JSON Size (kb) | Serialization Time (ops/s) | Deserialization Time (ops/s) | Throughput (GB/s) |
|
|
390
|
-
| ---------------- | -------------- | -------------------------- | ---------------------------- | ----------------- |
|
|
391
|
-
| Web API Response | [Fill Value] | [Fill Value] | [Fill Value] | [Fill Value] |
|
|
392
|
-
| Database Entry | [Fill Value] | [Fill Value] | [Fill Value] | [Fill Value] |
|
|
393
|
-
| File Parsing | [Fill Value] | [Fill Value] | [Fill Value] | [Fill Value] |
|
|
387
|
+
Note: the AssemblyScript benches are run using a _bump allocator_ so that Garbage Collection does not interfere with results. Also note that ideally, I would use [d8](https://v8.dev/docs/d8), but until that is done, these results serve as a temporary performance comparison.
|
|
388
|
+
|
|
389
|
+
**Table 1** - _AssemblyScript_
|
|
390
|
+
|
|
391
|
+
| Test Case | Size | Serialization (ops/s) | Deserialization (ops/s) | Serialization (MB/s) | Deserialization (MB/s) |
|
|
392
|
+
| --------------- | ---------- | --------------------- | ----------------------- | -------------------- | ---------------------- |
|
|
393
|
+
| Vector3 Object | 38 bytes | 35,714,285 ops/s | 35,435,552 ops/s | 1,357 MB/s | 1,348 MB/s |
|
|
394
|
+
| Alphabet String | 104 bytes | 13,617,021 ops/s | 18,390,804 ops/s | 1,416 MB/s | 1,986 MB/s |
|
|
395
|
+
| Small Object | 88 bytes | 24,242,424 ops/s | 12,307,692 ops/s | 2,133 MB/s | 1,083 MB/s |
|
|
396
|
+
| Medium Object | 494 bytes | 4,060,913 ops/s | 1,396,160 ops/s | 2,006 MB/s | 689.7 MB/s |
|
|
397
|
+
| Large Object | 3374 bytes | 614,754 ops/s | 132,802 ops/s | 2,074 MB/s | 448.0 MB/s |
|
|
398
|
+
|
|
399
|
+
**Table 2** - _JavaScript_
|
|
400
|
+
|
|
401
|
+
| Test Case | Size | Serialization (ops/s) | Deserialization (ops/s) | Serialization (MB/s) | Deserialization (MB/s) |
|
|
402
|
+
| --------------- | ---------- | --------------------- | ----------------------- | -------------------- | ---------------------- |
|
|
403
|
+
| Vector3 Object | 38 bytes | 8,791,209 ops/s | 5,369,12 ops/s | 357.4 MB/s | 204.3 MB/s |
|
|
404
|
+
| Alphabet String | 104 bytes | 13,793,103 ops/s | 14,746,544 ops/s | 1,416 MB/s | 1,592 MB/s |
|
|
405
|
+
| Small Object | 88 bytes | 8,376,963 ops/s | 4,968,944 ops/s | 737.1 MB/s | 437.2 MB/s |
|
|
406
|
+
| Medium Object | 494 bytes | 2,395,210 ops/s | 1,381,693 ops/s | 1,183 MB/s | 682.5 MB/s |
|
|
407
|
+
| Large Object | 3374 bytes | 222,222 ops/s | 117,233 ops/s | 749.7 MB/s | 395.5 MB/s |
|
|
394
408
|
|
|
395
409
|
## 📃 License
|
|
396
410
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { JSON } from "..";
|
|
2
|
+
import { bs } from "../../modules/as-bs";
|
|
3
|
+
import { bench } from "../custom/bench";
|
|
4
|
+
|
|
5
|
+
const v1 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
6
|
+
const v2 = '"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"';
|
|
7
|
+
|
|
8
|
+
bench(
|
|
9
|
+
"Serialize Alphabet",
|
|
10
|
+
() => {
|
|
11
|
+
JSON.stringify(v1);
|
|
12
|
+
},
|
|
13
|
+
64_000_00,
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
bench(
|
|
17
|
+
"Deserialize Alphabet",
|
|
18
|
+
() => {
|
|
19
|
+
JSON.parse<string>(v2);
|
|
20
|
+
},
|
|
21
|
+
64_000_00,
|
|
22
|
+
);
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { JSON } from "..";
|
|
2
|
+
import { bench } from "../custom/bench";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@json
|
|
6
|
+
class Vec3 {
|
|
7
|
+
public x!: i32;
|
|
8
|
+
public y!: i32;
|
|
9
|
+
public z!: i32;
|
|
10
|
+
|
|
11
|
+
@inline __SERIALIZE(ptr: usize): void {
|
|
12
|
+
bs.proposeSize(98);
|
|
13
|
+
store<u64>(bs.offset, 9570664606466171, 0); // {"x"
|
|
14
|
+
store<u16>(bs.offset, 58, 8); // :
|
|
15
|
+
bs.offset += 10;
|
|
16
|
+
JSON.__serialize<i32>(load<i32>(ptr, offsetof<this>("x")));
|
|
17
|
+
store<u64>(bs.offset, 9570668901433388, 0); // ,"y"
|
|
18
|
+
store<u16>(bs.offset, 58, 8); // :
|
|
19
|
+
bs.offset += 10;
|
|
20
|
+
JSON.__serialize<i32>(load<i32>(ptr, offsetof<this>("y")));
|
|
21
|
+
store<u64>(bs.offset, 9570673196400684, 0); // ,"z"
|
|
22
|
+
store<u16>(bs.offset, 58, 8); // :
|
|
23
|
+
bs.offset += 10;
|
|
24
|
+
JSON.__serialize<i32>(load<i32>(ptr, offsetof<this>("z")));
|
|
25
|
+
store<u16>(bs.offset, 125, 0); // }
|
|
26
|
+
bs.offset += 2;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@inline __INITIALIZE(): this {
|
|
30
|
+
return this;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@inline __DESERIALIZE(keyStart: usize, keyEnd: usize, valStart: usize, valEnd: usize, ptr: usize): void {
|
|
34
|
+
switch (load<u16>(keyStart)) {
|
|
35
|
+
case 120: {
|
|
36
|
+
// x
|
|
37
|
+
store<i32>(ptr, JSON.__deserialize<i32>(valStart, valEnd, 0), offsetof<this>("x"));
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
case 121: {
|
|
41
|
+
// y
|
|
42
|
+
store<i32>(ptr, JSON.__deserialize<i32>(valStart, valEnd, 0), offsetof<this>("y"));
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
case 122: {
|
|
46
|
+
// z
|
|
47
|
+
store<i32>(ptr, JSON.__deserialize<i32>(valStart, valEnd, 0), offsetof<this>("z"));
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@json
|
|
57
|
+
class LargeJSON {
|
|
58
|
+
public id!: i32;
|
|
59
|
+
public name!: string;
|
|
60
|
+
public age!: i32;
|
|
61
|
+
public email!: string;
|
|
62
|
+
public street!: string;
|
|
63
|
+
public city!: string;
|
|
64
|
+
public state!: string;
|
|
65
|
+
public zip!: string;
|
|
66
|
+
public tags!: string[];
|
|
67
|
+
public theme!: string;
|
|
68
|
+
public notifications!: boolean;
|
|
69
|
+
public language!: string;
|
|
70
|
+
public movement!: Vec3[];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const v1: LargeJSON = {
|
|
74
|
+
id: 2,
|
|
75
|
+
name: "Medium Object",
|
|
76
|
+
age: 18,
|
|
77
|
+
email: "me@jairus.dev",
|
|
78
|
+
street: "I don't want to say my street",
|
|
79
|
+
city: "I don't want to say this either",
|
|
80
|
+
state: "It really depends",
|
|
81
|
+
zip: "I forget what it is",
|
|
82
|
+
tags: ["me", "dogs", "mountains", "bar", "foo"],
|
|
83
|
+
theme: "Hyper Term Black",
|
|
84
|
+
notifications: true,
|
|
85
|
+
language: "en-US",
|
|
86
|
+
movement: [
|
|
87
|
+
{ x: 1, y: 2, z: 3 },
|
|
88
|
+
{ x: 1, y: 2, z: 3 },
|
|
89
|
+
{ x: 1, y: 2, z: 3 },
|
|
90
|
+
{ x: 1, y: 2, z: 3 },
|
|
91
|
+
{ x: 1, y: 2, z: 3 },
|
|
92
|
+
{ x: 1, y: 2, z: 3 },
|
|
93
|
+
{ x: 1, y: 2, z: 3 },
|
|
94
|
+
{ x: 1, y: 2, z: 3 },
|
|
95
|
+
{ x: 1, y: 2, z: 3 },
|
|
96
|
+
{ x: 1, y: 2, z: 3 },
|
|
97
|
+
{ x: 1, y: 2, z: 3 },
|
|
98
|
+
{ x: 1, y: 2, z: 3 },
|
|
99
|
+
{ x: 1, y: 2, z: 3 },
|
|
100
|
+
{ x: 1, y: 2, z: 3 },
|
|
101
|
+
{ x: 1, y: 2, z: 3 },
|
|
102
|
+
{ x: 1, y: 2, z: 3 },
|
|
103
|
+
{ x: 1, y: 2, z: 3 },
|
|
104
|
+
{ x: 1, y: 2, z: 3 },
|
|
105
|
+
{ x: 1, y: 2, z: 3 },
|
|
106
|
+
{ x: 1, y: 2, z: 3 },
|
|
107
|
+
{ x: 1, y: 2, z: 3 },
|
|
108
|
+
{ x: 1, y: 2, z: 3 },
|
|
109
|
+
{ x: 1, y: 2, z: 3 },
|
|
110
|
+
{ x: 1, y: 2, z: 3 },
|
|
111
|
+
{ x: 1, y: 2, z: 3 },
|
|
112
|
+
{ x: 1, y: 2, z: 3 },
|
|
113
|
+
{ x: 1, y: 2, z: 3 },
|
|
114
|
+
{ x: 1, y: 2, z: 3 },
|
|
115
|
+
{ x: 1, y: 2, z: 3 },
|
|
116
|
+
{ x: 1, y: 2, z: 3 },
|
|
117
|
+
{ x: 1, y: 2, z: 3 },
|
|
118
|
+
{ x: 1, y: 2, z: 3 },
|
|
119
|
+
{ x: 1, y: 2, z: 3 },
|
|
120
|
+
{ x: 1, y: 2, z: 3 },
|
|
121
|
+
{ x: 1, y: 2, z: 3 },
|
|
122
|
+
{ x: 1, y: 2, z: 3 },
|
|
123
|
+
{ x: 1, y: 2, z: 3 },
|
|
124
|
+
{ x: 1, y: 2, z: 3 },
|
|
125
|
+
{ x: 1, y: 2, z: 3 },
|
|
126
|
+
{ x: 1, y: 2, z: 3 },
|
|
127
|
+
{ x: 1, y: 2, z: 3 },
|
|
128
|
+
{ x: 1, y: 2, z: 3 },
|
|
129
|
+
{ x: 1, y: 2, z: 3 },
|
|
130
|
+
{ x: 1, y: 2, z: 3 },
|
|
131
|
+
{ x: 1, y: 2, z: 3 },
|
|
132
|
+
{ x: 1, y: 2, z: 3 },
|
|
133
|
+
{ x: 1, y: 2, z: 3 },
|
|
134
|
+
{ x: 1, y: 2, z: 3 },
|
|
135
|
+
{ x: 1, y: 2, z: 3 },
|
|
136
|
+
{ x: 1, y: 2, z: 3 },
|
|
137
|
+
{ x: 1, y: 2, z: 3 },
|
|
138
|
+
{ x: 1, y: 2, z: 3 },
|
|
139
|
+
{ x: 1, y: 2, z: 3 },
|
|
140
|
+
{ x: 1, y: 2, z: 3 },
|
|
141
|
+
{ x: 1, y: 2, z: 3 },
|
|
142
|
+
{ x: 1, y: 2, z: 3 },
|
|
143
|
+
{ x: 1, y: 2, z: 3 },
|
|
144
|
+
{ x: 1, y: 2, z: 3 },
|
|
145
|
+
{ x: 1, y: 2, z: 3 },
|
|
146
|
+
{ x: 1, y: 2, z: 3 },
|
|
147
|
+
{ x: 1, y: 2, z: 3 },
|
|
148
|
+
{ x: 1, y: 2, z: 3 },
|
|
149
|
+
{ x: 1, y: 2, z: 3 },
|
|
150
|
+
{ x: 1, y: 2, z: 3 },
|
|
151
|
+
{ x: 1, y: 2, z: 3 },
|
|
152
|
+
{ x: 1, y: 2, z: 3 },
|
|
153
|
+
{ x: 1, y: 2, z: 3 },
|
|
154
|
+
{ x: 1, y: 2, z: 3 },
|
|
155
|
+
],
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
const v2 = `{"id":2,"name":"Medium Object","age":18,"email":"me@jairus.dev","street":"I don't want to say my street","city":"I don't want to say this either","state":"It really depends","zip":"I forget what it is","tags":["me","dogs","mountains","bar","foo"],"theme":"Hyper Term Black","notifications":true,"language":"en-US","movement":[{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3}]}`;
|
|
159
|
+
|
|
160
|
+
bench(
|
|
161
|
+
"Serialize Medium Object",
|
|
162
|
+
() => {
|
|
163
|
+
JSON.stringify(v1);
|
|
164
|
+
},
|
|
165
|
+
3_000_00,
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
bench(
|
|
169
|
+
"Deserialize Medium Object",
|
|
170
|
+
() => {
|
|
171
|
+
JSON.parse<LargeJSON>(v2);
|
|
172
|
+
},
|
|
173
|
+
3_000_00,
|
|
174
|
+
);
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { JSON } from "..";
|
|
2
|
+
import { bench } from "../custom/bench";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@json
|
|
6
|
+
class MediumJSON {
|
|
7
|
+
public id!: i32;
|
|
8
|
+
public name!: string;
|
|
9
|
+
public age!: i32;
|
|
10
|
+
public email!: string;
|
|
11
|
+
public street!: string;
|
|
12
|
+
public city!: string;
|
|
13
|
+
public state!: string;
|
|
14
|
+
public zip!: string;
|
|
15
|
+
public tags!: string[];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const v1: MediumJSON = {
|
|
19
|
+
id: 2,
|
|
20
|
+
name: "Medium Object",
|
|
21
|
+
age: 18,
|
|
22
|
+
email: "me@jairus.dev",
|
|
23
|
+
street: "I don't want to say my street",
|
|
24
|
+
city: "I don't want to say this either",
|
|
25
|
+
state: "It really depends",
|
|
26
|
+
zip: "I forget what it is",
|
|
27
|
+
tags: ["me", "dogs", "mountains", "bar", "foo"],
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const v2 = `{"id":2,"name":"Medium Object","age":18,"email":"me@jairus.dev","street":"I don't want to say my street","city":"I don't want to say this either","state":"It really depends","zip":"I forget what it is","tags":["me","dogs","mountains","bar","foo"]}`;
|
|
31
|
+
|
|
32
|
+
bench(
|
|
33
|
+
"Serialize Medium Object",
|
|
34
|
+
() => {
|
|
35
|
+
JSON.stringify(v1);
|
|
36
|
+
},
|
|
37
|
+
8_000_00,
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
bench(
|
|
41
|
+
"Deserialize Medium Object",
|
|
42
|
+
() => {
|
|
43
|
+
JSON.parse<MediumJSON>(v2);
|
|
44
|
+
},
|
|
45
|
+
8_000_00,
|
|
46
|
+
);
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { JSON } from "..";
|
|
2
|
+
import { bench } from "../custom/bench";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@json
|
|
6
|
+
class SmallJSON {
|
|
7
|
+
public id!: i32;
|
|
8
|
+
public name!: string;
|
|
9
|
+
public active!: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const v1: SmallJSON = {
|
|
13
|
+
id: 1,
|
|
14
|
+
name: "Small Object",
|
|
15
|
+
active: true,
|
|
16
|
+
};
|
|
17
|
+
const v2 = '{"id":1,"name":"Small Object","active":true}';
|
|
18
|
+
|
|
19
|
+
bench(
|
|
20
|
+
"Serialize Small Object",
|
|
21
|
+
() => {
|
|
22
|
+
JSON.stringify(v1);
|
|
23
|
+
},
|
|
24
|
+
16_000_00,
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
bench(
|
|
28
|
+
"Deserialize Small Object",
|
|
29
|
+
() => {
|
|
30
|
+
JSON.parse<SmallJSON>(v2);
|
|
31
|
+
},
|
|
32
|
+
16_000_00,
|
|
33
|
+
);
|