Skip to content

Commit

Permalink
micro-optimisations
Browse files Browse the repository at this point in the history
  • Loading branch information
MrFoxPro committed Sep 13, 2024
1 parent dc56567 commit 27b5572
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 51 deletions.
67 changes: 26 additions & 41 deletions serde-generate/runtime/typescript/serde.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,21 +83,21 @@ export abstract class BinaryWriter implements Writer {
public static readonly BIG_64Fs = 18446744073709551615n
public static readonly TEXT_ENCODER = new TextEncoder()

public buffer = new ArrayBuffer(64)
public buffer = new ArrayBuffer(8)
public offset = 0

private ensureBufferWillHandleSize(bytes: number) {
const wishSize = this.offset + bytes
if (wishSize > this.buffer.byteLength) {
let newBufferLength = this.buffer.byteLength
while (newBufferLength < wishSize) newBufferLength *= 2
newBufferLength = Math.max(wishSize, newBufferLength)

// TODO: there is new API for resizing buffer, but in Node it seems to be slower then allocating new
// this.buffer.resize(newBufferLength)
const newBuffer = new ArrayBuffer(newBufferLength)
new Uint8Array(newBuffer).set(new Uint8Array(this.buffer))
this.buffer = newBuffer

const newBuffer = new Uint8Array(newBufferLength)
newBuffer.set(new Uint8Array(this.buffer))
this.buffer = newBuffer.buffer
}
}

Expand Down Expand Up @@ -155,17 +155,17 @@ export abstract class BinaryWriter implements Writer {
}

public writeU64(value: bigint | number) {
const low = BigInt(value) & BinaryWriter.BIG_32Fs
const high = BigInt(value) >> BinaryWriter.BIG_32
const low = BigInt(value) & BinaryWriter.BIG_32Fs,
high = BigInt(value) >> BinaryWriter.BIG_32

// write little endian number
this.writeU32(Number(low))
this.writeU32(Number(high))
}

public writeU128(value: bigint | number) {
const low = BigInt(value) & BinaryWriter.BIG_64Fs
const high = BigInt(value) >> BinaryWriter.BIG_64
const low = BigInt(value) & BinaryWriter.BIG_64Fs,
high = BigInt(value) >> BinaryWriter.BIG_64

// write little endian number
this.writeU64(low)
Expand Down Expand Up @@ -194,17 +194,17 @@ export abstract class BinaryWriter implements Writer {
}

public writeI64(value: bigint | number) {
const low = BigInt(value) & BinaryWriter.BIG_32Fs
const high = BigInt(value) >> BinaryWriter.BIG_32
const low = BigInt(value) & BinaryWriter.BIG_32Fs,
high = BigInt(value) >> BinaryWriter.BIG_32

// write little endian number
this.writeI32(Number(low))
this.writeI32(Number(high))
}

public writeI128(value: bigint | number) {
const low = BigInt(value) & BinaryWriter.BIG_64Fs
const high = BigInt(value) >> BinaryWriter.BIG_64
const low = BigInt(value) & BinaryWriter.BIG_64Fs,
high = BigInt(value) >> BinaryWriter.BIG_64

// write little endian number
this.writeI64(low)
Expand Down Expand Up @@ -245,7 +245,7 @@ export abstract class BinaryWriter implements Writer {
}

public getBytes() {
return new Uint8Array(this.buffer).slice(0, this.offset)
return new Uint8Array(this.buffer.slice(0, this.offset))
}
}

Expand All @@ -261,21 +261,21 @@ export abstract class BinaryReader implements Reader {
// copies data to prevent outside mutation of buffer.
this.buffer = new ArrayBuffer(data.length)
new Uint8Array(this.buffer).set(data, 0)

this.readOptionTag = this.readBool
}

private read(length: number) {
const bytes = this.buffer.slice(this.offset, this.offset + length)
this.offset += length
return bytes
return this.buffer.slice(this.offset, (this.offset = this.offset + length))
}

abstract readLength(): number
abstract readVariantIndex(): number
abstract readOptionTag(): boolean
abstract checkThatKeySlicesAreIncreasing(key1: [number, number], key2: [number, number]): void

public readString() {
const value = this.readBytes()
return BinaryReader.TEXT_DECODER.decode(value)
return BinaryReader.TEXT_DECODER.decode(this.readBytes())
}

public readBytes() {
Expand All @@ -287,8 +287,7 @@ export abstract class BinaryReader implements Reader {
}

public readBool() {
const bool = new Uint8Array(this.read(1))[0]
return bool == 1
return new Uint8Array(this.read(1))[0] === 1
}

public readUnit() {
Expand All @@ -308,17 +307,13 @@ export abstract class BinaryReader implements Reader {
}

public readU64() {
const low = this.readU32()
const high = this.readU32()

const low = this.readU32(), high = this.readU32()
// combine the two 32-bit values and return (little endian)
return (BigInt(high) << BinaryReader.BIG_32) | BigInt(low)
}

public readU128() {
const low = this.readU64()
const high = this.readU64()

const low = this.readU64(), high = this.readU64()
// combine the two 64-bit values and return (little endian)
return (high << BinaryReader.BIG_64) | low
}
Expand All @@ -336,28 +331,20 @@ export abstract class BinaryReader implements Reader {
}

public readI64() {
const low = this.readI32()
const high = this.readI32()

const low = this.readI32(), high = this.readI32()
// combine the two 32-bit values and return (little endian)
return (BigInt(high) << BinaryReader.BIG_32) | BigInt(low)
}

public readI128() {
const low = this.readI64()
const high = this.readI64()

const low = this.readI64(), high = this.readI64()
// combine the two 64-bit values and return (little endian)
return (high << BinaryReader.BIG_64) | low
}

public readOptionTag() {
return this.readBool()
}

public readList<T>(readFn: () => T, listLength?: number) {
const length = listLength ?? this.readLength()
const list = new Array<T>(length)
const length = listLength ?? this.readLength(), list = new Array<T>(length)
for (let i = 0; i < length; i++) list[i] = readFn()
return list
}
Expand All @@ -366,9 +353,7 @@ export abstract class BinaryReader implements Reader {
const length = this.readLength(), obj = new Map<K, V>()
let previousKeyStart = 0, previousKeyEnd = 0
for (let i = 0; i < length; i++) {
const keyStart = this.offset,
key = readKey(),
keyEnd = this.offset
const keyStart = this.offset, key = readKey(), keyEnd = this.offset
if (i > 0) {
this.checkThatKeySlicesAreIncreasing([previousKeyStart, previousKeyEnd], [keyStart, keyEnd])
}
Expand Down
26 changes: 16 additions & 10 deletions suite/typescript/ts/bench.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,35 @@ const ComplexStruct_pb_obj: ProtobufRegistry.ComplexStruct = {
}

await async function bench_encode() {
const b = new Bench({ time: 1_000 })
const b = new Bench({ time: 1_500 })

b.add('serdegen-bincode:encode', () => {
BincodeRegistry.ComplexStruct.encode(Data.ComplexStruct_obj)
})

b.add('JSON:encode', () => {
JSON.stringify(Data.ComplexStruct_obj)
})
b.add('protobuf-js-ts-proto:encode', () => {
ProtobufRegistry.ComplexStruct.encode(ComplexStruct_pb_obj)
})
b.add('serdegen-bincode:encode', () => {
BincodeRegistry.ComplexStruct.encode(Data.ComplexStruct_obj)
})

await b.warmup()
await b.run()
b.results.sort((x, y) => x.hz - y.hz)

console.table(b.table())
}()



await async function bench_decode() {
const b = new Bench({ time: 1_000 })
const b = new Bench({ time: 1_500 })

const bincodec_encoded = BincodeRegistry.ComplexStruct.encode(Data.ComplexStruct_obj)
b.add('serdegen-bincode:decode', () => {
BincodeRegistry.ComplexStruct.decode(bincodec_encoded)
})

const json_encoded = JSON.stringify(Data.ComplexStruct_obj)
b.add('JSON:decode', () => {
Expand All @@ -49,13 +58,10 @@ await async function bench_decode() {
ProtobufRegistry.ComplexStruct.decode(pb_encoded)
})

const bincodec_encoded = BincodeRegistry.ComplexStruct.encode(Data.ComplexStruct_obj)
b.add('serdegen-bincode:decode', () => {
BincodeRegistry.ComplexStruct.decode(bincodec_encoded)
})

await b.warmup()
await b.run()
b.results.sort((x, y) => x.hz - y.hz)

console.table(b.table())
}()

0 comments on commit 27b5572

Please sign in to comment.