diff --git a/README.md b/README.md index 4113dee..202ab29 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,7 @@ Serialization Benchmarks: | Value | JavaScript (ops/s) | JSON-as (ops/s) | JSON-AS with Pages | |----------------------------|--------------------|-----------------|--------------------| | "hello world" | 28,629,598 | 64,210,666 | + 124% | -| 12345 | 31,562,431 | 48,035,001 | 316,518,756 ops/s | +| 12345 | 31,562,431 | 56,329,066 | 321,783,941 ops/s | | 1.2345 | 15,977,278 | 20,322,939 | 30,307,616 ops/s | | [[],[[]],[[],[[]]]] | 8,998,624 | 34,453,102 | + 283% | diff --git a/assembly/bench/bench.ts b/assembly/bench/bench.ts index 66fab9b..3f6fd69 100644 --- a/assembly/bench/bench.ts +++ b/assembly/bench/bench.ts @@ -2,7 +2,7 @@ import { bench, blackbox } from "as-bench/assembly/bench"; import { Sink } from "../src/sink"; import { JSON } from ".."; import { serializeString } from "../serialize/string"; - +/* const set = JSON.Value.from([ JSON.Value.from([]), JSON.Value.from([ @@ -15,14 +15,15 @@ const set = JSON.Value.from([ ]), ]), ]); - +*/ const page = Sink.withCapacity(65536); -/* + +let i = 1000000; bench("Serialize Integer", () => { blackbox(JSON.serialize(12345, page)); + //if (--i == 0) { page.reset(); i = 1000000; } }); - - +/* bench("Serialize Set Theoretical Representation", () => { blackbox(JSON.serialize(set,page)); page.reset(); @@ -35,7 +36,7 @@ bench("Serialize Float", () => { bench("Serialize Float32", () => { blackbox(JSON.serialize(1.2345, page)); page.reset(); -});*/ +}); bench("Serialize String", () => { blackbox(serializeString("hello world", page)); }); diff --git a/assembly/serialize/integer.ts b/assembly/serialize/integer.ts index 613f1e3..2abcb83 100644 --- a/assembly/serialize/integer.ts +++ b/assembly/serialize/integer.ts @@ -1,49 +1,185 @@ import { Sink } from "../src/sink"; @inline export function serializeInteger(data: T, out: Sink | null = null): Sink { - if (!out) out = Sink.withCapacity(0); - return out.writeNumber(data); + if (!out) out = Sink.withCapacity(10); + return utoa32(data, out); } -@inline export function utoa16(data: u32): string { - const str = changetype(__new(10, idof())); - const buf = changetype(str); +@inline export function utoa32(data: T, out: Sink): Sink { + let buf = changetype(out.buffer) + out.offset; const fix4_28 = (1 << 28) / 10000; - let tmp = data * (fix4_28 + 1) - (data / 4); - store(buf, 48 + (tmp >> 28)); - tmp = (tmp & 0x0fffffff) * 10; - - store(buf, 48 + (tmp >> 28), 2); - tmp = (tmp & 0x0fffffff) * 10; - - store(buf, 48 + (tmp >> 28), 4); - tmp = (tmp & 0x0fffffff) * 10; - - store(buf, 48 + (tmp >> 28), 6); - tmp = (tmp & 0x0fffffff) * 10; - - store(buf, 48 + (tmp >> 28), 8); - return str -} - -@inline function utoa32(buf: usize, data: u32): void { const low = data % 10000; const high = data / 10000; - const fix4_28 = (1 << 28) / 10000; - let tmp = data * (fix4_28 + 1) - (data / 4); - - store(buf, 48 + (tmp >> 28)); - tmp = (tmp & 0x0fffffff) * 10; - - store(buf, 48 + (tmp >> 28), 2); - tmp = (tmp & 0x0fffffff) * 10; - store(buf, 48 + (tmp >> 28), 4); - tmp = (tmp & 0x0fffffff) * 10; + let tmpLow = low * (fix4_28 + 1) - (low >> 2); + let tmpHigh = high * (fix4_28 + 1) - (high >> 2); - store(buf, 48 + (tmp >> 28), 6); - tmp = (tmp & 0x0fffffff) * 10; + let fnd: bool = false; - store(buf, 48 + (tmp >> 28), 8); + { + const v = tmpHigh >> 28; + if (!fnd) { + if (v == 0) { + buf -= 2; + tmpHigh = (tmpHigh & 0x0fffffff) * 10; + } else { + fnd = true; + store(buf, 48 + v); + tmpHigh = (tmpHigh & 0x0fffffff) * 10; + out.offset += 2; + } + } else { + store(buf, 48 + v); + tmpHigh = (tmpHigh & 0x0fffffff) * 10; + out.offset += 2; + } + } + { + const v = tmpHigh >> 28; + if (!fnd) { + if (v == 0) { + buf -= 2; + tmpHigh = (tmpHigh & 0x0fffffff) * 10; + } else { + fnd = true; + store(buf, 48 + v, 2); + tmpHigh = (tmpHigh & 0x0fffffff) * 10; + out.offset += 2; + } + } else { + store(buf, 48 + v, 2); + tmpHigh = (tmpHigh & 0x0fffffff) * 10; + out.offset += 2; + } + } + { + const v = tmpHigh >> 28; + if (!fnd) { + if (v == 0) { + buf -= 2; + tmpHigh = (tmpHigh & 0x0fffffff) * 10; + } else { + fnd = true; + store(buf, 48 + v, 4); + tmpHigh = (tmpHigh & 0x0fffffff) * 10; + out.offset += 2; + } + } else { + store(buf, 48 + v, 4); + tmpHigh = (tmpHigh & 0x0fffffff) * 10; + out.offset += 2; + } + } + { + const v = tmpHigh >> 28; + if (!fnd) { + if (v == 0) { + buf -= 2; + tmpHigh = (tmpHigh & 0x0fffffff) * 10; + } else { + fnd = true; + store(buf, 48 + v, 6); + tmpHigh = (tmpHigh & 0x0fffffff) * 10; + out.offset += 2; + } + } else { + store(buf, 48 + v, 6); + tmpHigh = (tmpHigh & 0x0fffffff) * 10; + out.offset += 2; + } + } + { + const v = tmpHigh >> 28; + if (!fnd) { + if (v == 0) { + buf -= 2; + tmpHigh = (tmpHigh & 0x0fffffff) * 10; + } else { + fnd = true; + store(buf, 48 + v, 8); + tmpHigh = (tmpHigh & 0x0fffffff) * 10; + out.offset += 2; + } + } else { + store(buf, 48 + v, 8); + tmpHigh = (tmpHigh & 0x0fffffff) * 10; + out.offset += 2; + } + } + { + const v = tmpLow >> 28; + if (!fnd) { + if (v == 0) { + buf -= 2; + tmpLow = (tmpLow & 0x0fffffff) * 10; + } else { + fnd = true; + store(buf, 48 + v, 10); + tmpLow = (tmpLow & 0x0fffffff) * 10; + out.offset += 2; + } + } else { + store(buf, 48 + v, 10); + tmpLow = (tmpLow & 0x0fffffff) * 10; + out.offset += 2; + } + } + { + const v = tmpLow >> 28; + if (!fnd) { + if (v == 0) { + buf -= 2; + tmpLow = (tmpLow & 0x0fffffff) * 10; + } else { + fnd = true; + store(buf, 48 + v, 12); + tmpLow = (tmpLow & 0x0fffffff) * 10; + out.offset += 2; + } + } else { + store(buf, 48 + v, 12); + tmpLow = (tmpLow & 0x0fffffff) * 10; + out.offset += 2; + } + } + { + const v = tmpLow >> 28; + if (!fnd) { + if (v == 0) { + buf -= 2; + tmpLow = (tmpLow & 0x0fffffff) * 10; + } else { + fnd = true; + store(buf, 48 + v, 14); + tmpLow = (tmpLow & 0x0fffffff) * 10; + out.offset += 2; + } + } else { + store(buf, 48 + v, 14); + tmpLow = (tmpLow & 0x0fffffff) * 10; + out.offset += 2; + } + } + { + const v = tmpLow >> 28; + if (!fnd) { + if (v == 0) { + buf -= 2; + tmpLow = (tmpLow & 0x0fffffff) * 10; + } else { + fnd = true; + store(buf, 48 + v, 16); + tmpLow = (tmpLow & 0x0fffffff) * 10; + out.offset += 2; + } + } else { + store(buf, 48 + v, 16); + tmpLow = (tmpLow & 0x0fffffff) * 10; + out.offset += 2; + } + } + store(buf, 48 + (tmpLow >> 28), 18); + out.offset += 2; + return out; } \ No newline at end of file diff --git a/assembly/src/json.ts b/assembly/src/json.ts index 5644682..3c1e1a6 100644 --- a/assembly/src/json.ts +++ b/assembly/src/json.ts @@ -1,4 +1,4 @@ -import { StringSink } from "as-string-sink/assembly"; + import { StringSink } from "as-string-sink/assembly"; import { isSpace } from "util/string"; import { aCode, diff --git a/assembly/test.ts b/assembly/test.ts index a16bb62..6cbfe19 100644 --- a/assembly/test.ts +++ b/assembly/test.ts @@ -1,5 +1,5 @@ import { JSON } from "."; -import { utoa16 } from "./serialize/integer"; +import { utoa32 } from "./serialize/integer"; import { Sink } from "./src/sink"; import { describe, expect } from "as-test/assembly"; @@ -9,8 +9,8 @@ describe("Serialize String", () => { describe("Serialize Integer", () => { expect(JSON.serialize(65536).toString()).toBe("65536"); - expect(utoa16(65536)).toBe("65536"); - console.log(utoa16(6553)) + expect(utoa32(65536, Sink.withCapacity(20)).toString()).toBe("65536"); + console.log(utoa32(6553, Sink.withCapacity(20)).toString()) }); describe("Serialize Float", () => { expect(JSON.serialize(3.1415).toString()).toBe("3.1415");