diff --git a/assembly/custom/itoa.ts b/assembly/custom/itoa.ts new file mode 100644 index 0000000..d3f5981 --- /dev/null +++ b/assembly/custom/itoa.ts @@ -0,0 +1,41 @@ +const f1_10000 = 26844; + +@inline export function itoa_fast(out: usize, val: u32): void { + const low = val % 100000; + const high = val / 100000; + + let tmp_high = high * (f1_10000) - (high / 4); + let tmp_low = low * (f1_10000) - (low / 4); + + const h1 = 48 + (tmp_high >> 28); + tmp_high = (tmp_high & 0x0fffffff) * 5; + + const h2 = 48 + (tmp_high >> 27); + tmp_high = (tmp_high & 134217727) * 5; + + const h3 = 48 + (tmp_high >> 26); + tmp_high = (tmp_high & 67108863) * 5; + + const h4 = 48 + (tmp_high >> 25); + tmp_high = (tmp_high & 33554431) * 5; + + const h5 = 48 + (tmp_low >> 24); + + const l1 = 48 + (tmp_low >> 28); + tmp_low = (tmp_low & 0x0fffffff) * 5; + + const l2 = 48 + (tmp_low >> 27); + tmp_low = (tmp_low & 134217727) * 5; + + const l3 = 48 + (tmp_low >> 26); + tmp_low = (tmp_low & 67108863) * 5; + + const l4 = 48 + (tmp_low >> 25); + tmp_low = (tmp_low & 33554431) * 5; + + const l5 = 48 + (tmp_low >> 24); + + store(out, i32x4(h1 | (h2 << 16), h3 | (h4 << 16), h5 | (l1 << 16), l2 | (l3 << 16))); + store(out, l4 | (l5 << 16), 16); + +} \ No newline at end of file diff --git a/assembly/serialize/string.ts b/assembly/serialize/string.ts index b499700..0911785 100644 --- a/assembly/serialize/string.ts +++ b/assembly/serialize/string.ts @@ -11,12 +11,17 @@ import { OBJECT, TOTAL_OVERHEAD } from "rt/common"; import { bs } from "../custom/bs"; import { _intTo16, intTo16 } from "../custom/util"; + // @ts-ignore: Decorator valid here @inline export function serializeString(data: string): string { + return bs.out();x +} +// @ts-ignore: Decorator valid here +@inline export function serializeString_BS(data: string): void { const len = data.length << 1; if (len === 0) { bs.write_32(2228258); /* "" */ - return bs.out(); + return; } bs.write_16(QUOTE); @@ -80,5 +85,4 @@ import { _intTo16, intTo16 } from "../custom/util"; } bs.write_s_se_u(data, last, changetype(changetype(data) - TOTAL_OVERHEAD).rtSize); bs.write_16(QUOTE); - return bs.out(); } \ No newline at end of file diff --git a/assembly/test.ts b/assembly/test.ts index 3087d80..94a5005 100644 --- a/assembly/test.ts +++ b/assembly/test.ts @@ -1,14 +1,5 @@ -// import { JSON } from "."; -import { JSON } from "."; +import { itoa_fast } from "./custom/itoa"; -@json -class ContentBlock { - @omitnull() - input: JSON.Raw | null = null; -} - -const foo: ContentBlock = { - input: "123" -} - -console.log(JSON.stringify(foo)) \ No newline at end of file +const out = changetype(new ArrayBuffer(40)); +itoa_fast(out, 1234567890); +console.log(String.UTF16.decodeUnsafe(out, 20)); \ No newline at end of file diff --git a/bench/benchmark.ts b/bench/benchmark.ts index 4f5db48..43c7bcd 100644 --- a/bench/benchmark.ts +++ b/bench/benchmark.ts @@ -1,6 +1,8 @@ import { bench } from "as-bench/assembly/bench"; import { serializeString } from "../assembly/serialize/string"; import { bs } from "../assembly/custom/bs"; +import { itoa_fast } from "../assembly/custom/itoa"; +import { itoa_buffered } from "util/number"; @json class Vec3 { @@ -20,13 +22,21 @@ const vec: Vec3 = { y: 1, z: 8, }; -bench("Stringify Vec3", () => { - vec.__SERIALIZE_BS(); - //bs.reset() -}); -bench("Stringify String", () => { - serializeString("Hello World"); + +bench("itoa fast", () => { + itoa_fast(out, 1234567890) }); + +bench("itoa", () => { + itoa_buffered(out, 1234567890) +}) +// bench("Stringify Vec3", () => { +// vec.__SERIALIZE_BS(); +// //bs.reset() +// }); +// bench("Stringify String", () => { +// serializeString("Hello World"); +// }); /* bench("Parse Number SNIP", () => { blackbox(snip_fast("12345")); diff --git a/bench/benchmark.wasm b/bench/benchmark.wasm index d5fba6d..5d7004d 100644 Binary files a/bench/benchmark.wasm and b/bench/benchmark.wasm differ diff --git a/package.json b/package.json index 602c7ae..2b2b338 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "scripts": { "test": "ast test && rm -rf ./build/", "pretest": "rm -rf ./build/ && ast build", - "build:test": "rm -rf ./build/ && JSON_DEBUG=true asc assembly/test.ts --transform ./transform -o ./build/test.wasm", + "build:test": "rm -rf ./build/ && JSON_DEBUG=true asc assembly/test.ts --transform ./transform -o ./build/test.wasm --enable simd", "build:bench": "asc bench/benchmark.ts -o bench/benchmark.wasm --transform ./transform --optimizeLevel 3 --shrinkLevel 0 --converge --noAssert --uncheckedBehavior always --runtime stub --enable simd", "bench:wasmtime": "wasmtime ./bench/benchmark.wasm", "bench:wasmer": "wasmer --llvm ./bench/benchmark.wasm",