json-as 1.1.19 → 1.1.20

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.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Change Log
2
2
 
3
+ ## 2025-07-14 - 1.1.20
4
+
5
+ - feat: enable SIMD string serialization
6
+
3
7
  ## 2025-06-30 - 1.1.19
4
8
 
5
9
  - fix: wrong path used in `readFileSync` when importing from a library
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
  ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
7
7
  █████ ███████ ██████ ██ ████ ██ ██ ███████
8
8
  </span>
9
- AssemblyScript - v1.1.19
9
+ AssemblyScript - v1.1.20
10
10
  </pre>
11
11
  </h6>
12
12
 
@@ -391,7 +391,7 @@ These benchmarks compare this library to JavaScript's native `JSON.stringify` an
391
391
  | Test Case | Size | Serialization (ops/s) | Deserialization (ops/s) | Serialization (MB/s) | Deserialization (MB/s) |
392
392
  | --------------- | ---------- | --------------------- | ----------------------- | -------------------- | ---------------------- |
393
393
  | Vector3 Object | 38 bytes | 26,611,226 ops/s | 32,160,804 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 |
394
+ | Alphabet String | 104 bytes | 16,916,886 ops/s | 18,390,804 ops/s | 1,759 MB/s | 1,986 MB/s |
395
395
  | Small Object | 88 bytes | 24,242,424 ops/s | 12,307,692 ops/s | 2,133 MB/s | 1,083 MB/s |
396
396
  | Medium Object | 494 bytes | 4,060,913 ops/s | 1,396,160 ops/s | 2,006 MB/s | 689.7 MB/s |
397
397
  | Large Object | 3374 bytes | 479,616 ops/s | 132,802 ops/s | 2,074 MB/s | 448.0 MB/s |
@@ -401,7 +401,7 @@ These benchmarks compare this library to JavaScript's native `JSON.stringify` an
401
401
  | Test Case | Size | Serialization (ops/s) | Deserialization (ops/s) | Serialization (MB/s) | Deserialization (MB/s) |
402
402
  | --------------- | ---------- | --------------------- | ----------------------- | -------------------- | ---------------------- |
403
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 |
404
+ | Alphabet String | 104 bytes | 12,830,228 ops/s | 12,140,296 ops/s | 1,334 MB/s | 1,311 MB/s |
405
405
  | Small Object | 88 bytes | 8,376,963 ops/s | 4,968,944 ops/s | 737.1 MB/s | 437.2 MB/s |
406
406
  | Medium Object | 494 bytes | 2,395,210 ops/s | 1,381,693 ops/s | 1,183 MB/s | 682.5 MB/s |
407
407
  | Large Object | 3374 bytes | 222,222 ops/s | 117,233 ops/s | 749.7 MB/s | 395.5 MB/s |
@@ -5,20 +5,28 @@ import { bench } from "./lib/bench";
5
5
  const v1 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
6
6
  const v2 = '"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"';
7
7
 
8
+ const blackBoxArea = memory.data(64);
8
9
  expect(JSON.stringify(v1)).toBe(v2);
9
10
 
10
11
  bench(
11
12
  "Serialize Alphabet",
12
13
  () => {
13
- inline.always(JSON.stringify(v1));
14
+ blackbox(inline.always(JSON.stringify(blackbox(v1))));
14
15
  },
15
- 64_000_00,
16
+ 24_000_00,
17
+ v1.length << 1,
16
18
  );
17
19
 
18
20
  bench(
19
21
  "Deserialize Alphabet",
20
22
  () => {
21
- inline.always(JSON.parse<string>(v2));
23
+ blackbox(inline.always(JSON.parse<string>(blackbox(v2))));
22
24
  },
23
- 64_000_00,
25
+ 24_000_00,
26
+ v2.length << 1,
24
27
  );
28
+
29
+ function blackbox<T>(value: T): T {
30
+ store<T>(blackBoxArea, value);
31
+ return load<T>(blackBoxArea);
32
+ }
@@ -1,20 +1,32 @@
1
- export function bench(description: string, routine: () => void, ops: u64 = 1_000_000): void {
1
+ export function bench(description: string, routine: () => void, ops: u64 = 1_000_000, bytesPerOp: u64 = 0): void {
2
2
  console.log(" - Benchmarking " + description);
3
+
3
4
  let warmup = ops / 10;
4
5
  while (--warmup) {
5
6
  routine();
6
7
  }
7
- const start = Date.now();
8
+
9
+ const start = performance.now();
10
+
8
11
  let count = ops;
9
- while (count != 0) {
12
+ while (count--) {
10
13
  routine();
11
- count--;
12
14
  }
13
- const elapsed = Date.now() - start;
14
15
 
15
- let opsPerSecond = (ops * 1000) / elapsed;
16
+ const end = performance.now();
17
+ const elapsed = Math.max(1, end - start);
18
+
19
+ const opsPerSecond = f64(ops * 1000) / elapsed;
20
+
21
+ let log = ` Completed benchmark in ${formatNumber(u64(Math.round(elapsed)))}ms at ${formatNumber(u64(Math.round(opsPerSecond)))} ops/s`;
22
+
23
+ if (bytesPerOp > 0) {
24
+ const totalBytes = bytesPerOp * ops;
25
+ const mbPerSec = f64(totalBytes) / (elapsed / 1000) / (1000 * 1000);
26
+ log += ` @ ${formatNumber(u64(Math.round(mbPerSec)))}MB/s`;
27
+ }
16
28
 
17
- console.log(` Completed benchmark in ${formatNumber(elapsed)}ms at ${formatNumber(opsPerSecond)} ops/s\n`);
29
+ console.log(log + "\n");
18
30
  }
19
31
 
20
32
  function formatNumber(n: u64): string {
package/assembly/index.ts CHANGED
@@ -27,6 +27,8 @@ import { serializeObject } from "./serialize/simple/object";
27
27
  import { deserializeObject } from "./deserialize/simple/object";
28
28
  import { serializeRaw } from "./serialize/simple/raw";
29
29
  import { deserializeRaw } from "./deserialize/simple/raw";
30
+ import { serializeString_SIMD } from "./serialize/simd/string";
31
+ // import { deserializeString_SIMD } from "./deserialize/simd/string";
30
32
 
31
33
  /**
32
34
  * Offset of the 'storage' property in the JSON.Value class.
@@ -112,11 +114,11 @@ export namespace JSON {
112
114
  // bs.setBuffer(oldBuf);
113
115
  // return changetype<string>(newBuf);
114
116
  // }
115
- // if (ASC_FEATURE_SIMD) {
116
- // serializeString_SIMD(data as string);
117
- // } else {
118
- serializeString(data as string);
119
- // }
117
+ if (ASC_FEATURE_SIMD) {
118
+ serializeString_SIMD(data as string);
119
+ } else {
120
+ serializeString(data as string);
121
+ }
120
122
  return bs.out<string>();
121
123
  // @ts-ignore: Supplied by transform
122
124
  } else if (isDefined(data.__SERIALIZE)) {
@@ -179,7 +181,7 @@ export namespace JSON {
179
181
  } else if (isString<T>()) {
180
182
  if (dataSize < 4) throw new Error("Cannot parse data as string because it was formatted incorrectly!");
181
183
  // if (ASC_FEATURE_SIMD) {
182
- // // @ts-ignore
184
+ // // @ts-ignore
183
185
  // return changetype<string>(deserializeString_SIMD(dataPtr, dataPtr + dataSize, __new(dataSize - 4, idof<string>())));
184
186
  // } else {
185
187
  // @ts-ignore
@@ -426,7 +428,7 @@ export namespace JSON {
426
428
  // @ts-ignore: type
427
429
  private storage: Map<string, JSON.Value> = new Map<string, JSON.Value>();
428
430
 
429
- constructor() {}
431
+ constructor() { }
430
432
 
431
433
  // @ts-ignore: decorator
432
434
  @inline get size(): i32 {
@@ -542,7 +544,11 @@ export namespace JSON {
542
544
  store<u64>(bs.offset, 30399761348886638);
543
545
  bs.offset += 8;
544
546
  } else if (isString<nonnull<T>>()) {
545
- serializeString(src as string);
547
+ if (ASC_FEATURE_SIMD) {
548
+ serializeString_SIMD(src as string);
549
+ } else {
550
+ serializeString(src as string);
551
+ }
546
552
  // @ts-ignore: Supplied by transform
547
553
  } else if (isDefined(src.__SERIALIZE_CUSTOM)) {
548
554
  // @ts-ignore
@@ -714,12 +720,12 @@ export namespace JSON {
714
720
  // bs.setBuffer(oldBuf);
715
721
  // return changetype<string>(newBuf);
716
722
  // }
717
- // if (ASC_FEATURE_SIMD) {
718
- // serializeString_SIMD(data as string);
719
- // } else {
720
- bs.saveState();
721
- serializeString(data as string);
722
- // }
723
+ if (ASC_FEATURE_SIMD) {
724
+ serializeString_SIMD(data as string);
725
+ } else {
726
+ bs.saveState();
727
+ serializeString(data as string);
728
+ }
723
729
  return bs.cpyOut<string>();
724
730
  // @ts-ignore: Supplied by transform
725
731
  } else if (isDefined(data.__SERIALIZE)) {
@@ -3,6 +3,8 @@ import { BACK_SLASH } from "../../custom/chars";
3
3
  import { SERIALIZE_ESCAPE_TABLE } from "../../globals/tables";
4
4
  import { bytes } from "../../util";
5
5
 
6
+ const U00_MARKER = 13511005048209500;
7
+
6
8
  /**
7
9
  * Serializes strings into their JSON counterparts using SIMD operations
8
10
  * @param srcStart pointer to begin serializing at
@@ -13,20 +15,20 @@ export function serializeString_SIMD(src: string): void {
13
15
  const SPLAT_92 = i16x8.splat(92); /* \ */
14
16
 
15
17
  const SPLAT_32 = i16x8.splat(32); /* [ESC] */
16
- const SPLAT_0 = i16x8.splat(0); /* 0 */
17
18
 
18
19
  const srcSize = bytes(src);
19
20
  let srcStart = changetype<usize>(src);
20
21
  const srcEnd = srcStart + srcSize;
21
22
  const srcEnd16 = srcEnd - 16;
22
23
 
23
- bs.proposeSize(srcSize + 4);
24
+ bs.proposeSize(srcSize + 40);
24
25
 
25
26
  store<u8>(changetype<usize>(bs.offset), 34); /* " */
26
27
  bs.offset += 2;
27
28
 
28
29
  while (srcStart <= srcEnd16) {
29
30
  const block = v128.load(srcStart);
31
+
30
32
  v128.store(bs.offset, block);
31
33
 
32
34
  const backslash_indices = i16x8.eq(block, SPLAT_92);
@@ -38,21 +40,20 @@ export function serializeString_SIMD(src: string): void {
38
40
 
39
41
  while (mask != 0) {
40
42
  const lane_index = ctz(mask) << 1;
41
- const dst_offset = bs.offset + lane_index;
42
43
  const src_offset = srcStart + lane_index;
43
44
  const code = load<u16>(src_offset) << 2;
44
45
  const escaped = load<u32>(SERIALIZE_ESCAPE_TABLE + code);
45
-
46
46
  mask &= mask - 1;
47
-
48
47
  if ((escaped & 0xffff) != BACK_SLASH) {
49
48
  bs.growSize(10);
50
- store<u64>(dst_offset, 13511005048209500);
49
+ const dst_offset = bs.offset + lane_index;
50
+ store<u64>(dst_offset, U00_MARKER);
51
51
  store<u32>(dst_offset, escaped, 8);
52
52
  v128.store(dst_offset, v128.load(src_offset, 2), 12);
53
53
  bs.offset += 10;
54
54
  } else {
55
55
  bs.growSize(2);
56
+ const dst_offset = bs.offset + lane_index;
56
57
  store<u32>(dst_offset, escaped);
57
58
  v128.store(dst_offset, v128.load(src_offset, 2), 4);
58
59
  bs.offset += 2;
@@ -63,101 +64,13 @@ export function serializeString_SIMD(src: string): void {
63
64
  bs.offset += 16;
64
65
  }
65
66
 
66
- const rem = srcEnd - srcStart;
67
- if (rem & 8) {
68
- const block = v128.load64_zero(srcStart);
69
- v128.store64_lane(bs.offset, block, 0);
70
-
71
- const backslash_indices = i16x8.eq(block, SPLAT_92);
72
- const quote_indices = i16x8.eq(block, SPLAT_34);
73
- const escape_indices = i16x8.lt_u(block, SPLAT_32);
74
- const zero_indices = i16x8.eq(block, SPLAT_0);
75
- const sieve = v128.and(v128.or(v128.or(backslash_indices, quote_indices), escape_indices), v128.not(zero_indices));
76
-
77
- let mask = i16x8.bitmask(sieve);
78
- while (mask != 0) {
79
- let lane_index = ctz(mask) << 1;
80
- const dst_offset = bs.offset + lane_index;
81
- const src_offset = srcStart + lane_index;
82
- const code = load<u16>(src_offset) << 2;
83
- const escaped = load<u32>(SERIALIZE_ESCAPE_TABLE + code);
84
- mask &= mask - 1;
85
-
86
- if ((escaped & 0xffff) != BACK_SLASH) {
87
- bs.growSize(10);
88
- store<u64>(dst_offset, 13511005048209500);
89
- store<u32>(dst_offset, escaped, 8);
90
- while (lane_index < 6) {
91
- store<u8>(bs.offset + lane_index, load<u8>(srcStart + lane_index, 2), 12);
92
- lane_index += 2;
93
- }
94
- bs.offset += 10;
95
- } else {
96
- bs.growSize(2);
97
- store<u32>(dst_offset, escaped);
98
-
99
- while (lane_index < 6) {
100
- store<u8>(bs.offset + lane_index, load<u8>(srcStart + lane_index, 2), 4);
101
- lane_index += 2;
102
- }
103
- bs.offset += 2;
104
- }
105
- }
106
-
107
- bs.offset += 8;
108
- srcStart += 8;
109
- }
110
- if (rem & 4) {
111
- const block = load<u32>(srcStart);
112
- const codeA = block & 0xffff;
113
- const codeB = (block >> 16) & 0xffff;
114
-
115
- if (codeA == 92 || codeA == 34 || codeA < 32) {
116
- const escaped = load<u32>(SERIALIZE_ESCAPE_TABLE + (codeA << 2));
117
-
118
- if ((escaped & 0xffff) != BACK_SLASH) {
119
- bs.growSize(10);
120
- store<u64>(bs.offset, 13511005048209500);
121
- store<u32>(bs.offset, escaped, 8);
122
- bs.offset += 12;
123
- } else {
124
- bs.growSize(2);
125
- store<u32>(bs.offset, escaped);
126
- bs.offset += 4;
127
- }
128
- } else {
129
- store<u16>(bs.offset, codeA);
130
- bs.offset += 2;
131
- }
132
-
133
- if (codeB == 92 || codeB == 34 || codeB < 32) {
134
- const escaped = load<u32>(SERIALIZE_ESCAPE_TABLE + (codeB << 2));
135
-
136
- if ((escaped & 0xffff) != BACK_SLASH) {
137
- bs.growSize(10);
138
- store<u64>(bs.offset, 13511005048209500);
139
- store<u32>(bs.offset, escaped, 8);
140
- bs.offset += 12;
141
- } else {
142
- bs.growSize(2);
143
- store<u32>(bs.offset, escaped);
144
- bs.offset += 4;
145
- }
146
- } else {
147
- store<u16>(bs.offset, codeB);
148
- bs.offset += 2;
149
- }
150
-
151
- srcStart += 4;
152
- }
153
- if (rem & 2) {
67
+ while (srcStart <= srcEnd - 2) {
154
68
  const code = load<u16>(srcStart);
155
69
  if (code == 92 || code == 34 || code < 32) {
156
70
  const escaped = load<u32>(SERIALIZE_ESCAPE_TABLE + (code << 2));
157
-
158
71
  if ((escaped & 0xffff) != BACK_SLASH) {
159
72
  bs.growSize(10);
160
- store<u64>(bs.offset, 13511005048209500);
73
+ store<u64>(bs.offset, U00_MARKER);
161
74
  store<u32>(bs.offset, escaped, 8);
162
75
  bs.offset += 12;
163
76
  } else {
@@ -169,6 +82,7 @@ export function serializeString_SIMD(src: string): void {
169
82
  store<u16>(bs.offset, code);
170
83
  bs.offset += 2;
171
84
  }
85
+ srcStart += 2;
172
86
  }
173
87
 
174
88
  store<u8>(bs.offset, 34); /* " */
@@ -1,6 +1,7 @@
1
1
  import { JSON } from "../assembly/index";
2
2
  import { bs } from "../lib/as-bs";
3
3
 
4
+
4
5
  @json
5
6
  class Vec3 {
6
7
  x: f32 = 0;
@@ -24,6 +25,7 @@ class Vec3 {
24
25
  bs.offset += 2;
25
26
  }
26
27
 
28
+
27
29
  @inline
28
30
  __INITIALIZE(): this {
29
31
  return this;
@@ -204,6 +206,7 @@ class Vec3 {
204
206
  }
205
207
  }
206
208
 
209
+
207
210
  @json
208
211
  class Player {
209
212
 
@@ -212,6 +215,7 @@ class Player {
212
215
  lastName!: string;
213
216
  lastActive!: Array<i32>;
214
217
 
218
+
215
219
  @omitif((self: this): boolean => self.age < 18)
216
220
  age!: i32;
217
221
  pos!: Vec3 | null;
@@ -260,6 +264,7 @@ class Player {
260
264
  bs.offset += 2;
261
265
  }
262
266
 
267
+
263
268
  @inline
264
269
  __INITIALIZE(): this {
265
270
  store<string>(changetype<usize>(this), "", offsetof<this>("lastName"));
@@ -6,15 +6,22 @@ const v2 = '"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"';
6
6
  bench(
7
7
  "Serialize Alphabet",
8
8
  () => {
9
- JSON.stringify(v1);
9
+ blackbox(JSON.stringify(blackbox(v1)));
10
10
  },
11
11
  64_000_00,
12
+ v1.length << 1,
12
13
  );
13
14
 
14
15
  bench(
15
16
  "Deserialize Alphabet",
16
17
  () => {
17
- JSON.parse(v2);
18
+ blackbox(JSON.parse(blackbox(v2)));
18
19
  },
19
20
  64_000_00,
21
+ v2.length << 1,
20
22
  );
23
+
24
+ function blackbox<T>(value: T): T {
25
+ (globalThis as any).__blackhole = value;
26
+ return globalThis.__blackhole;
27
+ }
@@ -1,27 +1,42 @@
1
- if (typeof console === "undefined") {
2
- console = {
3
- log: print,
4
- error: print,
5
- warn: print,
6
- };
7
- }
8
-
9
- export function bench(description: string, routine: () => void, ops: number = 1_000_000): void {
1
+ export function bench(description: string, routine: () => void, ops: number = 1_000_000, bytesPerOp: number = 0): void {
10
2
  console.log(" - Benchmarking " + description);
11
- let warmup = ops / 10;
12
- while (--warmup) {
3
+
4
+ let warmup = Math.floor(ops / 10);
5
+ while (warmup-- > 0) {
13
6
  routine();
14
7
  }
15
- const start = Date.now();
8
+
9
+ const start = performance.now();
10
+
16
11
  let count = ops;
17
- while (count !== 0) {
12
+ while (count-- > 0) {
18
13
  routine();
19
- count--;
20
14
  }
21
- const elapsed = Date.now() - start;
22
15
 
23
- const opsPerSecond = Math.round((ops * 1000) / elapsed);
24
- const format = new Intl.NumberFormat("en-US");
16
+ const end = performance.now();
17
+ const elapsed = Math.max(1, end - start);
18
+
19
+ const opsPerSecond = (ops * 1000) / elapsed;
20
+
21
+ let log = ` Completed benchmark in ${formatNumber(Math.round(elapsed))}ms at ${formatNumber(Math.round(opsPerSecond))} ops/s`;
22
+
23
+ if (bytesPerOp > 0) {
24
+ const totalBytes = bytesPerOp * ops;
25
+ const mbPerSec = totalBytes / (elapsed / 1000) / (1000 * 1000);
26
+ log += ` @ ${formatNumber(Math.round(mbPerSec))}MB/s`;
27
+ }
28
+
29
+ console.log(log + "\n");
30
+ }
25
31
 
26
- console.log(` Completed benchmark in ${format.format(elapsed)}ms at ${format.format(opsPerSecond)} ops/s\n`);
32
+ function formatNumber(n: number): string {
33
+ let str = n.toString();
34
+ let len = str.length;
35
+ let result = "";
36
+ let commaOffset = len % 3;
37
+ for (let i = 0; i < len; i++) {
38
+ if (i > 0 && (i - commaOffset) % 3 === 0) result += ",";
39
+ result += str.charAt(i);
40
+ }
41
+ return result;
27
42
  }
@@ -10,6 +10,7 @@ const { exports } = new WebAssembly.Instance(module, {
10
10
  console.log(__liftString(ptr));
11
11
  },
12
12
  "Date.now": () => Date.now(),
13
+ "performance.now": () => performance.now(),
13
14
  },
14
15
  });
15
16
 
package/bench.ts ADDED
@@ -0,0 +1,18 @@
1
+ import { Bench } from "tinybench";
2
+
3
+ const bench = new Bench({ time: 1000 });
4
+
5
+ const v1 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
6
+ const v2 = '"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"';
7
+
8
+ bench.add("Serialize Alphabet", () => {
9
+ JSON.stringify("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
10
+ });
11
+
12
+ bench.add("Deserialize Alphabet", () => {
13
+ JSON.parse('"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"');
14
+ });
15
+
16
+ bench.run().then(() => {
17
+ console.table(bench.table());
18
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "json-as",
3
- "version": "1.1.19",
3
+ "version": "1.1.20",
4
4
  "author": "Jairus Tanaka",
5
5
  "repository": {
6
6
  "type": "git",
@@ -9,10 +9,11 @@
9
9
  "main": "transform/lib/index.js",
10
10
  "devDependencies": {
11
11
  "@assemblyscript/wasi-shim": "^0.1.0",
12
- "@types/node": "^22.15.34",
12
+ "@types/node": "^24.0.8",
13
13
  "assemblyscript": "^0.28.2",
14
14
  "assemblyscript-prettier": "^3.0.1",
15
15
  "prettier": "^3.6.2",
16
+ "tinybench": "^4.0.1",
16
17
  "tsx": "^4.20.3",
17
18
  "typescript": "^5.8.3"
18
19
  },
package/run-bench.as.sh CHANGED
@@ -1,18 +1,17 @@
1
1
  #!/bin/bash
2
2
  RUNTIMES=${RUNTIMES:-"minimal stub"}
3
3
  ENGINES=${ENGINES:-"liftoff ignition sparkplug turbofan llvm"}
4
- for file in ./assembly/__benches__/medium.bench.ts; do
4
+ for file in ./assembly/__benches__/abc.bench.ts; do
5
5
  filename=$(basename -- "$file")
6
- output_wasi=
7
6
  for runtime in $RUNTIMES; do
8
- output="./build/${filename%.ts}.${runtime}.wasm"
7
+ output="./build/${filename%.ts}.${runtime}"
9
8
 
10
- npx asc "$file" --transform ./transform -o "${output}.1" -O3 --converge --noAssert --uncheckedBehavior always --runtime $runtime --enable simd --enable bulk-memory --exportStart start || {
9
+ npx asc "$file" --transform ./transform -o "${output}.1" -O3 --converge --noAssert --uncheckedBehavior always --runtime $runtime --enable bulk-memory --exportStart start || {
11
10
  echo "Build failed"
12
11
  exit 1
13
12
  }
14
13
 
15
- wasm-opt -all -O4 "${output}.1" -o "$output"
14
+ wasm-opt --enable-bulk-memory --enable-simd --enable-nontrapping-float-to-int --enable-tail-call -tnh -iit -ifwl -s 0 -O4 "${output}.1" -o "${output}.wasm"
16
15
  rm "${output}.1"
17
16
 
18
17
  npx asc "$file" --transform ./transform -o "${output}.2" -O3 --converge --noAssert --uncheckedBehavior always --runtime $runtime --enable simd --enable bulk-memory --config ./node_modules/@assemblyscript/wasi-shim/asconfig.json || {
@@ -20,7 +19,7 @@ for file in ./assembly/__benches__/medium.bench.ts; do
20
19
  exit 1
21
20
  }
22
21
 
23
- wasm-opt -all -O4 "${output}.2" -o "${output%.wasm}.wasi.wasm"
22
+ wasm-opt --enable-bulk-memory --enable-simd --enable-nontrapping-float-to-int --enable-tail-call -tnh -iit -ifwl -s 0 -O4 "${output}.2" -o "${output%.wasm}.wasi.wasm"
24
23
  rm "${output}.2"
25
24
 
26
25
  for engine in $ENGINES; do
@@ -44,7 +43,7 @@ for file in ./assembly/__benches__/medium.bench.ts; do
44
43
  fi
45
44
 
46
45
  if [[ "$engine" == "llvm" ]]; then
47
- wasmer run "${output%.wasm}.wasi.wasm" --llvm --enable-simd --enable-bulk-memory --enable-relaxed-simd --enable-pass-params-opt
46
+ wasmer run --llvm --enable-simd --enable-bulk-memory "${output}.wasi.wasm"
48
47
  fi
49
48
  done
50
49
  done
package/run-bench.js.sh CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/bin/bash
2
- RUNTIMES=${RUNTIMES:-"v8-liftoff v8-ignition v8-sparkplug v8-turbofan jsc-default"}
2
+ RUNTIMES=${RUNTIMES:-"liftoff ignition sparkplug turbofan"}
3
3
  npx tsc -p ./bench > /dev/null 2>&1
4
- for file in ./bench/*.bench.ts; do
4
+ for file in ./bench/abc.bench.ts; do
5
5
  filename=$(basename -- "$file")
6
6
  file_js="${filename%.ts}.js"
7
7
 
@@ -28,10 +28,6 @@ for file in ./bench/*.bench.ts; do
28
28
  if [[ "$engine" == "turbofan" ]]; then
29
29
  v8 --no-liftoff --no-wasm-tier-up --module ./build/$file_js
30
30
  fi
31
-
32
- if [[ "$engine" == "default" ]]; then
33
- jsc -m ./build/$file_js
34
- fi
35
31
  done
36
32
  done
37
33
 
package/bench.js DELETED
@@ -1,83 +0,0 @@
1
- import { Bench } from "tinybench";
2
- // Trying a new benchmarking lib.
3
-
4
- // JavaScript Results
5
- // ┌─────────┬───────────────────────────┬─────────────┬────────────────────┬──────────┬─────────┐
6
- // │ (index) │ Task Name │ ops / sec │ Average Time(ns) │ Margin │ Samples │
7
- // ├─────────┼───────────────────────────┼─────────────┼────────────────────┼──────────┼─────────┤
8
- // │ 0 │ 'Stringify Object (Vec3)' │ '817,816' │ 1222.76 │ '±3.55%' │ 81782 │
9
- // │ 1 │ 'Parse Object (Vec3)' │ '726,115' │ 1377.19 │ '±3.21%' │ 72612 │
10
- // │ 2 │ 'Stringify Number Array' │ '1,104,036' │ 905.77 │ '±6.48%' │ 110404 │
11
- // │ 3 │ 'Parse Number Array' │ '1,114,053' │ 897.62 │ '±2.58%' │ 111406 │
12
- // │ 4 │ 'Stringify String' │ '1,565,716' │ 638.69 │ '±2.04%' │ 156572 │
13
- // │ 5 │ 'Parse String' │ '69,568' │ 14374.22 │ '±2.55%' │ 6957 │
14
- // └─────────┴───────────────────────────┴─────────────┴────────────────────┴──────────┴─────────┘
15
-
16
- // AssemblyScript Results (Runtime Minimal)
17
- // ┌─────────┬───────────────────────────┬─────────────┬────────────────────┬──────────┬─────────┐
18
- // │ (index) │ Task Name │ ops / sec │ Average Time(ns) │ Diff │ Samples │
19
- // ├─────────┼───────────────────────────┼─────────────┼────────────────────┼──────────┼─────────┤
20
- // │ 0 │ 'Stringify Object (Vec3)' │ '2,091,000' │ 417.22 │ -805ns │ ------- │
21
- // │ 1 │ 'Parse Object (Vec3)' │ '1,780,000' │ 539.02 │ -838ns │ ------- |
22
- // │ 2 │ 'Stringify Number Array' │ '1,920,000' │ 445.43 │ -460ns │ ------- │
23
- // │ 3 │ 'Parse Number Array' │ '1,660,000' │ 597.17 │ -300ns │ ------- │
24
- // │ 4 │ 'Stringify String' │ '1,280,000' │ 736.27 │ +97ns │ ------- │
25
- // │ 5 │ 'Parse String' │ '4,230,000' │ 239.21 │ -14135ns │ ------- │
26
- // └─────────┴───────────────────────────┴─────────────┴────────────────────┴──────────┴─────────┘
27
-
28
- const vec = {
29
- x: 3,
30
- y: 1,
31
- z: 8,
32
- };
33
-
34
- let data;
35
-
36
- const bench = new Bench({ time: 1000 })
37
- .add("serialize vec3", () => (data = JSON.stringify(vec)))
38
- .add("deserialize vec3", () => {
39
- data = JSON.parse('{"x":3,"y":1,"z":8}');
40
- })
41
- .add("serialize alphabet string", () => {
42
- data = JSON.stringify("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~`!@#$%^&*()-_=+{[}]|\\:;\"'?/>.<,'\"}");
43
- })
44
- .add("deserialize alphabet string", () => {
45
- data = JSON.parse('"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~`!@#$%^&*()-_=+{[}]|\\\\:;\\"\'?/>.<,\'\\"}"');
46
- }) /*
47
- .add("parse float", () => {
48
- data = JSON.parse("1.2345")
49
- })
50
- .add("stringify iny", () => {
51
- data = JSON.stringify(12345)
52
- })
53
- .add("parse int", () => {
54
- data = JSON.parse("12345")
55
- })
56
- .add("Stringify Object (Vec3)", () => {
57
- data = JSON.stringify(vec);
58
- })
59
-
60
- .add("Parse Object (Vec3)", () => {
61
- data = JSON.parse('{"x":0,"y":0,"z":0}');
62
- })
63
-
64
- .add("Stringify Number Array", () => {
65
- data = JSON.stringify([1, 2, 3]);
66
- })
67
-
68
- .add("Parse Number Array", () => {
69
- data = JSON.parse("[1,2,3]");
70
- })
71
-
72
- .add("Stringify String", () => {
73
- data = JSON.stringify('Hello "World!');
74
- })
75
-
76
- .add("Parse String", () => {
77
- data = JSON.stringify('hello "world abc');
78
- })*/
79
- .todo("unimplemented .add");
80
-
81
- await bench.run();
82
-
83
- console.table(bench.table());