json-as 1.0.0 → 1.0.1
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/.github/workflows/{nodejs.yml → tests.yml} +1 -1
- package/CHANGELOG.md +4 -0
- package/README.md +60 -12
- package/assembly/__benches__/abc.bench.ts +21 -0
- package/assembly/__benches__/large.bench.ts +174 -0
- package/assembly/__benches__/lib/index.ts +26 -0
- package/assembly/__benches__/medium.bench.ts +46 -0
- package/assembly/__benches__/small.bench.ts +33 -0
- package/assembly/__benches__/vec3.bench.ts +72 -0
- 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/package.json +24 -27
- package/run-bench.as.sh +27 -0
- package/run-bench.js.sh +12 -0
- package/run-tests.sh +14 -2
- 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/bench/schemas.ts +0 -5
- package/bench/string.bench.ts +0 -16
- /package/bench/{bench.ts → lib/bench.ts} +0 -0
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
|
7
7
|
█████ ███████ ██████ ██ ████ ██ ██ ███████
|
|
8
8
|
</span>
|
|
9
|
-
AssemblyScript - v1.0.
|
|
9
|
+
AssemblyScript - v1.0.1
|
|
10
10
|
</pre>
|
|
11
11
|
</h5>
|
|
12
12
|
|
|
@@ -14,19 +14,17 @@
|
|
|
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
|
-
##
|
|
18
|
-
|
|
19
|
-
🔹Breaking changes to the way custom serializers/deserializers function (See Custom Serializers below)
|
|
17
|
+
## 🔭 What's new
|
|
20
18
|
|
|
21
19
|
🔹Major performance improvements and addition of SIMD
|
|
22
20
|
|
|
23
|
-
🔹
|
|
21
|
+
🔹Near zero-growth allocation design and low overhead
|
|
24
22
|
|
|
25
|
-
🔹
|
|
23
|
+
🔹Support for custom serializer and deserializers
|
|
26
24
|
|
|
27
|
-
🔹
|
|
25
|
+
🔹Fixes to many, many, bugs and edge cases
|
|
28
26
|
|
|
29
|
-
🔹
|
|
27
|
+
🔹Support for dynamic objects, arrays, arbitrary values, and raw types
|
|
30
28
|
|
|
31
29
|
## 📚 Contents
|
|
32
30
|
|
|
@@ -374,11 +372,13 @@ This allows custom serialization while maintaining a generic interface for the l
|
|
|
374
372
|
|
|
375
373
|
## ⚡ Performance
|
|
376
374
|
|
|
377
|
-
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
|
|
375
|
+
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 detailed statistics comparing performance metrics such as build time, operations-per-second, and throughput.
|
|
376
|
+
|
|
377
|
+
### 🔍 Comparison to JavaScript
|
|
378
378
|
|
|
379
|
-
|
|
379
|
+
These benchmarks compare this library to JavaScript's native `JSON.stringify` and `JSON.parse` functions.
|
|
380
380
|
|
|
381
|
-
**Table 1** -
|
|
381
|
+
**Table 1** - _AssemblyScript (LLVM)_
|
|
382
382
|
|
|
383
383
|
| Test Case | Size | Serialization (ops/s) | Deserialization (ops/s) | Serialization (MB/s) | Deserialization (MB/s) |
|
|
384
384
|
| --------------- | ---------- | --------------------- | ----------------------- | -------------------- | ---------------------- |
|
|
@@ -388,7 +388,7 @@ Note: the AssemblyScript benches are run using a _bump allocator_ so that Garbag
|
|
|
388
388
|
| Medium Object | 494 bytes | 4,060,913 ops/s | 1,396,160 ops/s | 2,006 MB/s | 689.7 MB/s |
|
|
389
389
|
| Large Object | 3374 bytes | 614,754 ops/s | 132,802 ops/s | 2,074 MB/s | 448.0 MB/s |
|
|
390
390
|
|
|
391
|
-
**Table 2** -
|
|
391
|
+
**Table 2** - _JavaScript (V8)_
|
|
392
392
|
|
|
393
393
|
| Test Case | Size | Serialization (ops/s) | Deserialization (ops/s) | Serialization (MB/s) | Deserialization (MB/s) |
|
|
394
394
|
| --------------- | ---------- | --------------------- | ----------------------- | -------------------- | ---------------------- |
|
|
@@ -398,6 +398,54 @@ Note: the AssemblyScript benches are run using a _bump allocator_ so that Garbag
|
|
|
398
398
|
| Medium Object | 494 bytes | 2,395,210 ops/s | 1,381,693 ops/s | 1,183 MB/s | 682.5 MB/s |
|
|
399
399
|
| Large Object | 3374 bytes | 222,222 ops/s | 117,233 ops/s | 749.7 MB/s | 395.5 MB/s |
|
|
400
400
|
|
|
401
|
+
**📌 Insights**
|
|
402
|
+
|
|
403
|
+
- JSON-AS consistently outperforms JavaScript's native implementation.
|
|
404
|
+
|
|
405
|
+
- **Serialization Speed:**
|
|
406
|
+
- JSON-AS achieves speeds up to `2,133 MB/s`, significantly faster than JavaScript's peak of `1,416 MB/s`.
|
|
407
|
+
- Large objects see the biggest improvement, with JSON-AS at `2,074 MB/s` vs. JavaScript’s `749.7 MB/s`.
|
|
408
|
+
|
|
409
|
+
- **Deserialization Speed:**
|
|
410
|
+
- JSON-AS reaches `1,986 MB/s`, while JavaScript caps at `1,592 MB/s`.
|
|
411
|
+
- Small and medium objects see the most significant performance boost overall.
|
|
412
|
+
|
|
413
|
+
### 📈 Comparison to v0.9.x version
|
|
414
|
+
|
|
415
|
+
**Table 1** - _v1.0.0_
|
|
416
|
+
|
|
417
|
+
| Test Case | Size | Serialization (ops/s) | Deserialization (ops/s) | Serialization (MB/s) | Deserialization (MB/s) |
|
|
418
|
+
| --------------- | ---------- | --------------------- | ----------------------- | -------------------- | ---------------------- |
|
|
419
|
+
| Vector3 Object | 38 bytes | 35,714,285 ops/s | 35,435,552 ops/s | 1,357 MB/s | 1,348 MB/s |
|
|
420
|
+
| Alphabet String | 104 bytes | 13,617,021 ops/s | 18,390,804 ops/s | 1,416 MB/s | 1,986 MB/s |
|
|
421
|
+
| Small Object | 88 bytes | 24,242,424 ops/s | 12,307,692 ops/s | 2,133 MB/s | 1,083 MB/s |
|
|
422
|
+
| Medium Object | 494 bytes | 4,060,913 ops/s | 1,396,160 ops/s | 2,006 MB/s | 689.7 MB/s |
|
|
423
|
+
| Large Object | 3374 bytes | 614,754 ops/s | 132,802 ops/s | 2,074 MB/s | 448.0 MB/s |
|
|
424
|
+
|
|
425
|
+
**Table 2** - _v0.9.29_
|
|
426
|
+
|
|
427
|
+
| Test Case | Size | Serialization (ops/s) | Deserialization (ops/s) | Serialization (MB/s) | Deserialization (MB/s) |
|
|
428
|
+
| --------------- | ---------- | --------------------- | ----------------------- | -------------------- | ---------------------- |
|
|
429
|
+
| Vector3 Object | 38 bytes | 6,896,551 ops/s | 10,958,904 ops/s | 262.1 MB/s | 416.4 MB/s |
|
|
430
|
+
| Alphabet String | 104 bytes | 5,128,205 ops/s | 8,695,652 ops/s | 533.3 MB/s | 939.1 MB/s |
|
|
431
|
+
| Small Object | 88 bytes | 4,953,560 ops/s | 3,678,160 ops/s | 435.9 MB/s | 323.7 MB/s |
|
|
432
|
+
| Medium Object | 494 bytes | 522,193 ops/s | 508,582 ops/s | 258.0 MB/s | 251.2 MB/s |
|
|
433
|
+
| Large Object | 3374 bytes | 51,229 ops/s | 65,585 ops/s | 172.8 MB/s | 221.3 MB/s |
|
|
434
|
+
|
|
435
|
+
**📌 Insights:**
|
|
436
|
+
|
|
437
|
+
- Massive performance improvements in JSON-AS `v1.0.0`:
|
|
438
|
+
- Serialization is **2-12x faster** (e.g., Large Object: `2,074 MB/s` vs. `172.8 MB/s`).
|
|
439
|
+
- Deserialization is **2-3x faster** (e.g., Large Object: `1,348 MB/s` vs. `221.3 MB/s`).
|
|
440
|
+
- Vector3 Object serialization improved from `416 MB/s` to `1,357 MB/s`--a **3x benefit** through new code generation techniques.
|
|
441
|
+
|
|
442
|
+
## 🔭 What's Next
|
|
443
|
+
|
|
444
|
+
- Theorize plans to keep key-order in generated schemas
|
|
445
|
+
- Generate optimized deserialization methods
|
|
446
|
+
- Inline specific hot code paths
|
|
447
|
+
- Implement error handling implementation
|
|
448
|
+
|
|
401
449
|
## 📃 License
|
|
402
450
|
|
|
403
451
|
This project is distributed under an open source license. You can view the full license using the following link: [License](./LICENSE)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { JSON } from "..";
|
|
2
|
+
import { bench } from "../custom/bench";
|
|
3
|
+
|
|
4
|
+
const v1 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
5
|
+
const v2 = '"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"';
|
|
6
|
+
|
|
7
|
+
bench(
|
|
8
|
+
"Serialize Alphabet",
|
|
9
|
+
() => {
|
|
10
|
+
JSON.stringify(v1);
|
|
11
|
+
},
|
|
12
|
+
1_000_00,
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
bench(
|
|
16
|
+
"Deserialize Alphabet",
|
|
17
|
+
() => {
|
|
18
|
+
JSON.parse<string>(v2);
|
|
19
|
+
},
|
|
20
|
+
1_000_00,
|
|
21
|
+
);
|
|
@@ -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,26 @@
|
|
|
1
|
+
export function describe(description: string, routine: () => void): void {
|
|
2
|
+
routine();
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function it(description: string, routine: () => void): void {
|
|
6
|
+
routine();
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function expect(left: string): Expectation {
|
|
10
|
+
return new Expectation(left);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
class Expectation {
|
|
14
|
+
public left: string;
|
|
15
|
+
|
|
16
|
+
constructor(left: string) {
|
|
17
|
+
this.left = left;
|
|
18
|
+
}
|
|
19
|
+
toBe(right: string): void {
|
|
20
|
+
if (this.left != right) {
|
|
21
|
+
console.log(" (expected) -> " + right);
|
|
22
|
+
console.log(" (received) -> " + this.left);
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -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
|
+
);
|
|
@@ -0,0 +1,72 @@
|
|
|
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
|
+
const v1: Vec3 = { x: 1, y: 2, z: 3 };
|
|
56
|
+
const v2 = '{"x":1,"y":2,"z":3}';
|
|
57
|
+
|
|
58
|
+
bench(
|
|
59
|
+
"Serialize Vec3",
|
|
60
|
+
() => {
|
|
61
|
+
JSON.stringify(v1);
|
|
62
|
+
},
|
|
63
|
+
16_000_00,
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
bench(
|
|
67
|
+
"Deserialize Vec3",
|
|
68
|
+
() => {
|
|
69
|
+
JSON.parse<Vec3>(v2);
|
|
70
|
+
},
|
|
71
|
+
16_000_00,
|
|
72
|
+
);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { bench } from "./lib/bench";
|
|
2
|
+
|
|
3
|
+
const v1 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
4
|
+
const v2 = '"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"';
|
|
5
|
+
|
|
6
|
+
bench(
|
|
7
|
+
"Serialize Alphabet",
|
|
8
|
+
() => {
|
|
9
|
+
JSON.stringify(v1);
|
|
10
|
+
},
|
|
11
|
+
64_000_00,
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
bench(
|
|
15
|
+
"Deserialize Alphabet",
|
|
16
|
+
() => {
|
|
17
|
+
JSON.parse(v2);
|
|
18
|
+
},
|
|
19
|
+
64_000_00,
|
|
20
|
+
);
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { bench } from "./lib/bench";
|
|
2
|
+
|
|
3
|
+
class Vec3 {
|
|
4
|
+
public x!: number;
|
|
5
|
+
public y!: number;
|
|
6
|
+
public z!: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
class LargeJSON {
|
|
10
|
+
public id!: number;
|
|
11
|
+
public name!: string;
|
|
12
|
+
public age!: number;
|
|
13
|
+
public email!: string;
|
|
14
|
+
public street!: string;
|
|
15
|
+
public city!: string;
|
|
16
|
+
public state!: string;
|
|
17
|
+
public zip!: string;
|
|
18
|
+
public tags!: string[];
|
|
19
|
+
public theme!: string;
|
|
20
|
+
public notifications!: boolean;
|
|
21
|
+
public language!: string;
|
|
22
|
+
public movement!: Vec3[];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const v1: LargeJSON = {
|
|
26
|
+
id: 2,
|
|
27
|
+
name: "Medium Object",
|
|
28
|
+
age: 18,
|
|
29
|
+
email: "me@jairus.dev",
|
|
30
|
+
street: "I don't want to say my street",
|
|
31
|
+
city: "I don't want to say this either",
|
|
32
|
+
state: "It really depends",
|
|
33
|
+
zip: "I forget what it is",
|
|
34
|
+
tags: ["me", "dogs", "mountains", "bar", "foo"],
|
|
35
|
+
theme: "Hyper Term Black",
|
|
36
|
+
notifications: true,
|
|
37
|
+
language: "en-US",
|
|
38
|
+
movement: [
|
|
39
|
+
{ x: 1, y: 2, z: 3 },
|
|
40
|
+
{ x: 1, y: 2, z: 3 },
|
|
41
|
+
{ x: 1, y: 2, z: 3 },
|
|
42
|
+
{ x: 1, y: 2, z: 3 },
|
|
43
|
+
{ x: 1, y: 2, z: 3 },
|
|
44
|
+
{ x: 1, y: 2, z: 3 },
|
|
45
|
+
{ x: 1, y: 2, z: 3 },
|
|
46
|
+
{ x: 1, y: 2, z: 3 },
|
|
47
|
+
{ x: 1, y: 2, z: 3 },
|
|
48
|
+
{ x: 1, y: 2, z: 3 },
|
|
49
|
+
{ x: 1, y: 2, z: 3 },
|
|
50
|
+
{ x: 1, y: 2, z: 3 },
|
|
51
|
+
{ x: 1, y: 2, z: 3 },
|
|
52
|
+
{ x: 1, y: 2, z: 3 },
|
|
53
|
+
{ x: 1, y: 2, z: 3 },
|
|
54
|
+
{ x: 1, y: 2, z: 3 },
|
|
55
|
+
{ x: 1, y: 2, z: 3 },
|
|
56
|
+
{ x: 1, y: 2, z: 3 },
|
|
57
|
+
{ x: 1, y: 2, z: 3 },
|
|
58
|
+
{ x: 1, y: 2, z: 3 },
|
|
59
|
+
{ x: 1, y: 2, z: 3 },
|
|
60
|
+
{ x: 1, y: 2, z: 3 },
|
|
61
|
+
{ x: 1, y: 2, z: 3 },
|
|
62
|
+
{ x: 1, y: 2, z: 3 },
|
|
63
|
+
{ x: 1, y: 2, z: 3 },
|
|
64
|
+
{ x: 1, y: 2, z: 3 },
|
|
65
|
+
{ x: 1, y: 2, z: 3 },
|
|
66
|
+
{ x: 1, y: 2, z: 3 },
|
|
67
|
+
{ x: 1, y: 2, z: 3 },
|
|
68
|
+
{ x: 1, y: 2, z: 3 },
|
|
69
|
+
{ x: 1, y: 2, z: 3 },
|
|
70
|
+
{ x: 1, y: 2, z: 3 },
|
|
71
|
+
{ x: 1, y: 2, z: 3 },
|
|
72
|
+
{ x: 1, y: 2, z: 3 },
|
|
73
|
+
{ x: 1, y: 2, z: 3 },
|
|
74
|
+
{ x: 1, y: 2, z: 3 },
|
|
75
|
+
{ x: 1, y: 2, z: 3 },
|
|
76
|
+
{ x: 1, y: 2, z: 3 },
|
|
77
|
+
{ x: 1, y: 2, z: 3 },
|
|
78
|
+
{ x: 1, y: 2, z: 3 },
|
|
79
|
+
{ x: 1, y: 2, z: 3 },
|
|
80
|
+
{ x: 1, y: 2, z: 3 },
|
|
81
|
+
{ x: 1, y: 2, z: 3 },
|
|
82
|
+
{ x: 1, y: 2, z: 3 },
|
|
83
|
+
{ x: 1, y: 2, z: 3 },
|
|
84
|
+
{ x: 1, y: 2, z: 3 },
|
|
85
|
+
{ x: 1, y: 2, z: 3 },
|
|
86
|
+
{ x: 1, y: 2, z: 3 },
|
|
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
|
+
],
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
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}]}`;
|
|
111
|
+
|
|
112
|
+
bench(
|
|
113
|
+
"Serialize Medium Object",
|
|
114
|
+
() => {
|
|
115
|
+
JSON.stringify(v1);
|
|
116
|
+
},
|
|
117
|
+
3_000_00,
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
bench(
|
|
121
|
+
"Deserialize Medium Object",
|
|
122
|
+
() => {
|
|
123
|
+
JSON.parse(v2);
|
|
124
|
+
},
|
|
125
|
+
3_000_00,
|
|
126
|
+
);
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { bench } from "./lib/bench";
|
|
2
|
+
|
|
3
|
+
class MediumJSON {
|
|
4
|
+
public id!: number;
|
|
5
|
+
public name!: string;
|
|
6
|
+
public age!: number;
|
|
7
|
+
public email!: string;
|
|
8
|
+
public street!: string;
|
|
9
|
+
public city!: string;
|
|
10
|
+
public state!: string;
|
|
11
|
+
public zip!: string;
|
|
12
|
+
public tags!: string[];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const v1: MediumJSON = {
|
|
16
|
+
id: 2,
|
|
17
|
+
name: "Medium Object",
|
|
18
|
+
age: 18,
|
|
19
|
+
email: "me@jairus.dev",
|
|
20
|
+
street: "I don't want to say my street",
|
|
21
|
+
city: "I don't want to say this either",
|
|
22
|
+
state: "It really depends",
|
|
23
|
+
zip: "I forget what it is",
|
|
24
|
+
tags: ["me", "dogs", "mountains", "bar", "foo"],
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
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"]}`;
|
|
28
|
+
|
|
29
|
+
bench(
|
|
30
|
+
"Serialize Medium Object",
|
|
31
|
+
() => {
|
|
32
|
+
JSON.stringify(v1);
|
|
33
|
+
},
|
|
34
|
+
8_000_00,
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
bench(
|
|
38
|
+
"Deserialize Medium Object",
|
|
39
|
+
() => {
|
|
40
|
+
JSON.parse(v2);
|
|
41
|
+
},
|
|
42
|
+
8_000_00,
|
|
43
|
+
);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { bench } from "./lib/bench";
|
|
2
|
+
|
|
3
|
+
class SmallJSON {
|
|
4
|
+
public id!: number;
|
|
5
|
+
public name!: string;
|
|
6
|
+
public active!: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const v1: SmallJSON = {
|
|
10
|
+
id: 1,
|
|
11
|
+
name: "Small Object",
|
|
12
|
+
active: true,
|
|
13
|
+
};
|
|
14
|
+
const v2 = '{"id":1,"name":"Small Object","active":true}';
|
|
15
|
+
|
|
16
|
+
bench(
|
|
17
|
+
"Serialize Small Object",
|
|
18
|
+
() => {
|
|
19
|
+
JSON.stringify(v1);
|
|
20
|
+
},
|
|
21
|
+
16_000_00,
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
bench(
|
|
25
|
+
"Deserialize Small Object",
|
|
26
|
+
() => {
|
|
27
|
+
JSON.parse(v2);
|
|
28
|
+
},
|
|
29
|
+
16_000_00,
|
|
30
|
+
);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { bench } from "./lib/bench";
|
|
2
|
+
|
|
3
|
+
class Vec3 {
|
|
4
|
+
public x!: number;
|
|
5
|
+
public y!: number;
|
|
6
|
+
public z!: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const v1: Vec3 = { x: 1, y: 2, z: 3 };
|
|
10
|
+
const v2 = '{"x":1,"y":2,"z":3}';
|
|
11
|
+
|
|
12
|
+
bench(
|
|
13
|
+
"Serialize Vec3",
|
|
14
|
+
() => {
|
|
15
|
+
JSON.stringify(v1);
|
|
16
|
+
},
|
|
17
|
+
16_000_00,
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
bench(
|
|
21
|
+
"Deserialize Vec3",
|
|
22
|
+
() => {
|
|
23
|
+
JSON.parse(v2);
|
|
24
|
+
},
|
|
25
|
+
16_000_00,
|
|
26
|
+
);
|
package/package.json
CHANGED
|
@@ -1,26 +1,41 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "json-as",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"author": "Jairus Tanaka",
|
|
5
|
+
"description": "The only JSON library you'll need for AssemblyScript. SIMD enabled",
|
|
6
|
+
"types": "assembly/index.ts",
|
|
7
|
+
"main": "transform/lib/index.js",
|
|
8
|
+
"homepage": "https://github.com/JairusSW/json-as#readme",
|
|
9
|
+
"license": "MIT",
|
|
5
10
|
"repository": {
|
|
6
11
|
"type": "git",
|
|
7
12
|
"url": "git+https://github.com/JairusSW/json-as.git"
|
|
8
13
|
},
|
|
9
|
-
"
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/JairusSW/json-as/issues"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"test": "bash ./run-tests.sh",
|
|
19
|
+
"bench:as": "bash ./run-bench.as.sh",
|
|
20
|
+
"bench:js": "bash ./run-bench.js.sh",
|
|
21
|
+
"build:time": "time npx asc ./assembly/__benches__/abc.bench.ts --transform ./transform -o ./build/abc.bench.wasm --optimizeLevel 3 --shrinkLevel 0 --converge --noAssert --uncheckedBehavior always --runtime stub --enable simd --enable bulk-memory",
|
|
22
|
+
"build:test": "rm -rf ./build/ && JSON_DEBUG=true asc --lib ./lib/ assembly/test.ts --transform ./transform -o ./build/test.wasm --textFile ./build/test.wat --optimizeLevel 3 --shrinkLevel 0",
|
|
23
|
+
"build:test:simd": "rm -rf ./build/ && JSON_DEBUG=true asc assembly/test.ts --transform ./transform -o ./build/test.wasm --textFile ./build/test.wat --optimizeLevel 3 --shrinkLevel 0 --enable simd",
|
|
24
|
+
"test:wasmtime": "wasmtime ./build/test.wasm",
|
|
25
|
+
"test:wasmer": "wasmer ./build/test.wasm",
|
|
26
|
+
"build:transform": "tsc -p ./transform",
|
|
27
|
+
"bench:wasmer": "wasmer ./build/bench.wasm --llvm",
|
|
28
|
+
"prettier": "prettier -w ."
|
|
29
|
+
},
|
|
10
30
|
"devDependencies": {
|
|
11
31
|
"@assemblyscript/wasi-shim": "^0.1.0",
|
|
12
32
|
"@types/node": "^22.13.1",
|
|
13
|
-
"as-bench": "JairusSW/as-bench",
|
|
14
|
-
"as-console": "^7.0.0",
|
|
15
|
-
"as-test": "^0.4.0-beta.3",
|
|
16
33
|
"assemblyscript": "^0.27.34",
|
|
17
34
|
"assemblyscript-prettier": "^3.0.1",
|
|
18
35
|
"prettier": "^3.5.0",
|
|
36
|
+
"tsx": "^4.19.3",
|
|
19
37
|
"typescript": "^5.7.3"
|
|
20
38
|
},
|
|
21
|
-
"bugs": {
|
|
22
|
-
"url": "https://github.com/JairusSW/json-as/issues"
|
|
23
|
-
},
|
|
24
39
|
"contributors": [
|
|
25
40
|
"DogWhich",
|
|
26
41
|
"Romdotdog",
|
|
@@ -31,8 +46,6 @@
|
|
|
31
46
|
"Matt Johnson-Pint",
|
|
32
47
|
"Tomáš Hromada"
|
|
33
48
|
],
|
|
34
|
-
"description": "The only JSON library you'll need for AssemblyScript. SIMD enabled",
|
|
35
|
-
"homepage": "https://github.com/JairusSW/json-as#readme",
|
|
36
49
|
"keywords": [
|
|
37
50
|
"assemblyscript",
|
|
38
51
|
"json",
|
|
@@ -48,24 +61,8 @@
|
|
|
48
61
|
"fast",
|
|
49
62
|
"algorithm"
|
|
50
63
|
],
|
|
51
|
-
"license": "MIT",
|
|
52
|
-
"overrides": {
|
|
53
|
-
"assemblyscript": "$assemblyscript"
|
|
54
|
-
},
|
|
55
64
|
"publishConfig": {
|
|
56
65
|
"@JairusSW:registry": "https://npm.pkg.github.com"
|
|
57
66
|
},
|
|
58
|
-
"
|
|
59
|
-
"test": "bash ./run-tests.sh",
|
|
60
|
-
"build:bench": "rm -rf ./build/ && JSON_DEBUG=true asc --lib ./lib/ assembly/__benches__/string.bench.ts -o ./build/bench.wasm --textFile ./build/bench.wat --transform ./transform --optimizeLevel 3 --shrinkLevel 0 --converge --noAssert --uncheckedBehavior always --runtime stub --enable simd --enable bulk-memory",
|
|
61
|
-
"build:test": "rm -rf ./build/ && JSON_DEBUG=true asc --lib ./lib/ assembly/test.ts --transform ./transform -o ./build/test.wasm --textFile ./build/test.wat --optimizeLevel 3 --shrinkLevel 0",
|
|
62
|
-
"build:test:simd": "rm -rf ./build/ && JSON_DEBUG=true asc assembly/test.ts --transform ./transform -o ./build/test.wasm --textFile ./build/test.wat --optimizeLevel 3 --shrinkLevel 0 --enable simd",
|
|
63
|
-
"test:wasmtime": "wasmtime ./build/test.wasm",
|
|
64
|
-
"test:wasmer": "wasmer ./build/test.wasm",
|
|
65
|
-
"build:transform": "tsc -p ./transform",
|
|
66
|
-
"bench:wasmer": "wasmer ./build/bench.wasm --llvm",
|
|
67
|
-
"prettier": "prettier -w ."
|
|
68
|
-
},
|
|
69
|
-
"type": "module",
|
|
70
|
-
"types": "assembly/index.ts"
|
|
67
|
+
"type": "module"
|
|
71
68
|
}
|
package/run-bench.as.sh
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
mkdir -p ./build
|
|
4
|
+
|
|
5
|
+
for file in ./assembly/__benches__/*.bench.ts; do
|
|
6
|
+
filename=$(basename -- "$file")
|
|
7
|
+
output="./build/${filename%.ts}.wasm"
|
|
8
|
+
|
|
9
|
+
start_time=$(date +%s%3N)
|
|
10
|
+
npx asc "$file" --transform ./transform -o "$output" --optimizeLevel 3 --shrinkLevel 0 --converge --noAssert --uncheckedBehavior always --runtime stub --enable simd --enable bulk-memory || { echo "Build failed"; exit 1; }
|
|
11
|
+
end_time=$(date +%s%3N)
|
|
12
|
+
|
|
13
|
+
build_time=$((end_time - start_time))
|
|
14
|
+
|
|
15
|
+
if [ "$build_time" -ge 60000 ]; then
|
|
16
|
+
formatted_time="$(bc <<< "scale=2; $build_time/60000")m"
|
|
17
|
+
elif [ "$build_time" -ge 1000 ]; then
|
|
18
|
+
formatted_time="$(bc <<< "scale=2; $build_time/1000")s"
|
|
19
|
+
else
|
|
20
|
+
formatted_time="${build_time}ms"
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
echo -e "$filename (built in $formatted_time)\n"
|
|
24
|
+
wasmer "$output" --llvm || { echo "Benchmarked failed."; exit 1; }
|
|
25
|
+
done
|
|
26
|
+
|
|
27
|
+
echo "Finished benchmarks."
|
package/run-bench.js.sh
ADDED
package/run-tests.sh
CHANGED
|
@@ -6,9 +6,21 @@ for file in ./assembly/__tests__/*.spec.ts; do
|
|
|
6
6
|
filename=$(basename -- "$file")
|
|
7
7
|
output="./build/${filename%.ts}.wasm"
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
start_time=$(date +%s%3N)
|
|
10
|
+
npx asc "$file" --transform ./transform --lib ./lib/ -o "$output" || { echo "Tests failed"; exit 1; }
|
|
11
|
+
end_time=$(date +%s%3N)
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
build_time=$((end_time - start_time))
|
|
14
|
+
|
|
15
|
+
if [ "$build_time" -ge 60000 ]; then
|
|
16
|
+
formatted_time="$(bc <<< "scale=2; $build_time/60000")m"
|
|
17
|
+
elif [ "$build_time" -ge 1000 ]; then
|
|
18
|
+
formatted_time="$(bc <<< "scale=2; $build_time/1000")s"
|
|
19
|
+
else
|
|
20
|
+
formatted_time="${build_time}ms"
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
echo " -> $filename (built in $formatted_time)"
|
|
12
24
|
wasmtime "$output" || { echo "Tests failed"; exit 1; }
|
|
13
25
|
done
|
|
14
26
|
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { bench } from "as-bench/assembly";
|
|
2
|
-
import { JSON } from "..";
|
|
3
|
-
import { Vec3 } from "./schemas";
|
|
4
|
-
import { serializeString_SIMD } from "../serialize/simd/string";
|
|
5
|
-
import { serializeString } from "../serialize/simple/string";
|
|
6
|
-
import { deserializeString } from "../deserialize/simple/string";
|
|
7
|
-
import { bytes } from "../util";
|
|
8
|
-
import { deserializeString_SIMD } from "../deserialize/simd/string";
|
|
9
|
-
|
|
10
|
-
const vec: Vec3 = {
|
|
11
|
-
x: 1,
|
|
12
|
-
y: 2,
|
|
13
|
-
z: 3
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
bs.ensureSize(4096);
|
|
17
|
-
// bench("Serialize Vector3", () => {
|
|
18
|
-
// JSON.stringify(vec);
|
|
19
|
-
// });
|
|
20
|
-
|
|
21
|
-
// bench("Deserialize Vector3", () => {
|
|
22
|
-
// JSON.parse<Vec3>('{"x":1,"y":2,"z":3}');
|
|
23
|
-
// });
|
|
24
|
-
|
|
25
|
-
// bench("Serialize String SIMD", () => {
|
|
26
|
-
// serializeString_SIMD("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~`!@#$%^&*()-_=+{[}]|\\:;\"'?/>.<,'\"}");
|
|
27
|
-
// bs.offset = changetype<usize>(bs.buffer);
|
|
28
|
-
// bs.stackSize = 0;
|
|
29
|
-
// });
|
|
30
|
-
|
|
31
|
-
// bench("Serialize String", () => {
|
|
32
|
-
// serializeString("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~`!@#$%^&*()-_=+{[}]|\\:;\"'?/>.<,'\"}");
|
|
33
|
-
// bs.offset = changetype<usize>(bs.buffer);
|
|
34
|
-
// bs.stackSize = 0;
|
|
35
|
-
// });
|
|
36
|
-
|
|
37
|
-
const src = '"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~`!@#$%^&*()-_=+{[}]|\\\\:;\\"\'?/>.<,\'\\"}"';
|
|
38
|
-
const srcStart = changetype<usize>(src);
|
|
39
|
-
const srcEnd = srcStart + bytes(src);
|
|
40
|
-
const out = changetype<usize>(new ArrayBuffer(256));
|
|
41
|
-
bench("Deserialize String", () => {
|
|
42
|
-
deserializeString(srcStart, srcEnd, out);
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
bench("Deserialize String SIMD", () => {
|
|
46
|
-
deserializeString_SIMD(srcStart, srcEnd, out);
|
|
47
|
-
})
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { JSON } from "..";
|
|
2
|
-
|
|
3
|
-
@json
|
|
4
|
-
export class Vec3 {
|
|
5
|
-
public x!: i32;
|
|
6
|
-
public y!: i32;
|
|
7
|
-
public z!: i32;
|
|
8
|
-
__DESERIALIZE(keyStart: usize, keyEnd: usize, valStart: usize, valEnd: usize, ptr: usize): void {
|
|
9
|
-
switch (load<u16>(keyStart)) {
|
|
10
|
-
case 120: { // x
|
|
11
|
-
store<i32>(ptr, JSON.__deserialize<i32>(valStart, valEnd, 0), offsetof<this>("x"));
|
|
12
|
-
return;
|
|
13
|
-
}
|
|
14
|
-
case 121: { // y
|
|
15
|
-
store<i32>(ptr, JSON.__deserialize<i32>(valStart, valEnd, 0), offsetof<this>("y"));
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
case 122: { // z
|
|
19
|
-
store<i32>(ptr, JSON.__deserialize<i32>(valStart, valEnd, 0), offsetof<this>("z"));
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import {JSON} from "..";
|
|
2
|
-
import {Vec3} from "./schemas";
|
|
3
|
-
import {bench} from "../custom/bench";
|
|
4
|
-
import {serializeString_SIMD} from "../serialize/simd/string";
|
|
5
|
-
import {deserializeString_SIMD} from "../deserialize/simd/string";
|
|
6
|
-
import {serializeString} from "../serialize/simple/string";
|
|
7
|
-
import {deserializeString} from "../deserialize/simple/string";
|
|
8
|
-
|
|
9
|
-
const vec: Vec3 = {x: 1, y: 2, z: 3};
|
|
10
|
-
|
|
11
|
-
bs.ensureSize(4096);
|
|
12
|
-
|
|
13
|
-
bench(
|
|
14
|
-
"Serialize String (Simple)",
|
|
15
|
-
() => {
|
|
16
|
-
serializeString("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~`!@#$%^&*()-_=+{[}]|\\:;\"'?/>.<,'\"}");
|
|
17
|
-
},
|
|
18
|
-
25_000_000
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
// bench("Deserialize String Simple", () => {
|
|
22
|
-
// deserializeString_SIMD("\"hello world\"")
|
|
23
|
-
// });
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import {JSON} from "..";
|
|
2
|
-
import {Vec3} from "./schemas";
|
|
3
|
-
import {bench} from "./bench";
|
|
4
|
-
|
|
5
|
-
const vec: Vec3 = {x: 1, y: 2, z: 3};
|
|
6
|
-
|
|
7
|
-
bs.ensureSize(4096);
|
|
8
|
-
bench(
|
|
9
|
-
"Serialize Vector3",
|
|
10
|
-
() => {
|
|
11
|
-
// JSON.__serialize(vec);
|
|
12
|
-
// bs.offset = changetype<usize>(bs.buffer);
|
|
13
|
-
// bs.stackSize = 0;
|
|
14
|
-
JSON.stringify(vec);
|
|
15
|
-
},
|
|
16
|
-
25_000_000
|
|
17
|
-
);
|
|
18
|
-
|
|
19
|
-
// bench("Deserialize Vector3", () => {
|
|
20
|
-
// JSON.parse<Vec3>('{"x":1,"y":2,"z":3}');
|
|
21
|
-
// });
|
package/bench/schemas.ts
DELETED
package/bench/string.bench.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { bench } from "./bench";
|
|
2
|
-
import { Vec3 } from "./schemas";
|
|
3
|
-
|
|
4
|
-
const vec: Vec3 = {
|
|
5
|
-
x: 1,
|
|
6
|
-
y: 2,
|
|
7
|
-
z: 3,
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
bench("Serialize Vector3", () => {
|
|
11
|
-
JSON.stringify(vec);
|
|
12
|
-
}, 25_000_000);
|
|
13
|
-
|
|
14
|
-
bench("Deserialize Vector3", () => {
|
|
15
|
-
JSON.parse('{"x":1,"y":2,"z":3}');
|
|
16
|
-
}, 25_000_000);
|
|
File without changes
|