From b6ea17129b2855008b27cdc150a58552d9d481ec Mon Sep 17 00:00:00 2001 From: Hans-Joachim Krauch Date: Tue, 5 Dec 2023 19:18:27 -0300 Subject: [PATCH] Do not create a new TextDecoder for every record (#1031) ### Public-Facing Changes Do not create a new TextDecoder for every record ### Description Massively improves read performance by avoiding unnecessary creation / cleanups of TextDecoders. Before: ``` [Summary]: ticks total nonlib name 6600 7.2% 46.1% JavaScript 7693 8.4% 53.8% C++ 21411 23.3% 149.6% GC 77489 84.4% Shared libraries 16 0.0% Unaccounted ``` After (Notice the drop in GC time): ``` [Summary]: ticks total nonlib name 3950 10.1% 60.7% JavaScript 2555 6.6% 39.2% C++ 549 1.4% 8.4% GC 32426 83.3% Shared libraries 5 0.0% Unaccounted ``` --- typescript/core/src/Reader.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/typescript/core/src/Reader.ts b/typescript/core/src/Reader.ts index c3c78f0b31..fcc2887237 100644 --- a/typescript/core/src/Reader.ts +++ b/typescript/core/src/Reader.ts @@ -1,9 +1,13 @@ import { getBigUint64 } from "./getBigUint64"; +// For performance reasons we use a single TextDecoder instance whose internal state is merely +// the encoding (defaults to UTF-8). This means that a TextDecoder.decode() call is not affected +// be previous calls. +const textDecoder = new TextDecoder(); + export default class Reader { #view: DataView; offset: number; - #textDecoder = new TextDecoder(); constructor(view: DataView, offset = 0) { this.#view = view; @@ -39,7 +43,7 @@ export default class Reader { if (this.offset + length > this.#view.byteLength) { throw new Error(`String length ${length} exceeds bounds of buffer`); } - const value = this.#textDecoder.decode( + const value = textDecoder.decode( new Uint8Array(this.#view.buffer, this.#view.byteOffset + this.offset, length), ); this.offset += length;