From 1299d2cdad260a472e98c40b51fd3f61da9e75da Mon Sep 17 00:00:00 2001 From: "FUJI Goro (gfx)" Date: Fri, 7 Jun 2019 22:59:37 +0900 Subject: [PATCH] experimental string cache in encoder but it's slow --- benchmark/string.ts | 12 ++++++------ src/Encoder.ts | 18 +++++++++++++++++- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/benchmark/string.ts b/benchmark/string.ts index e6b18708..6610c8b6 100644 --- a/benchmark/string.ts +++ b/benchmark/string.ts @@ -4,8 +4,8 @@ import { WASM_AVAILABLE } from "../src/wasmFunctions"; console.log(`WASM_AVAILABLE=${WASM_AVAILABLE}`); -const ascii = "A".repeat(40000); -const emoji = "🌏".repeat(20000); +const ascii = "A".repeat(30); +const emoji = "🌏".repeat(8); { // warm up ascii @@ -17,13 +17,13 @@ const emoji = "🌏".repeat(20000); // run console.time("encode ascii"); - for (let i = 0; i < 1000; i++) { + for (let i = 0; i < 1000000; i++) { encode(data); } console.timeEnd("encode ascii"); console.time("decode ascii"); - for (let i = 0; i < 1000; i++) { + for (let i = 0; i < 1000000; i++) { decode(encoded); } console.timeEnd("decode ascii"); @@ -40,13 +40,13 @@ const emoji = "🌏".repeat(20000); // run console.time("encode emoji"); - for (let i = 0; i < 1000; i++) { + for (let i = 0; i < 1000000; i++) { encode(data); } console.timeEnd("encode emoji"); console.time("decode emoji"); - for (let i = 0; i < 1000; i++) { + for (let i = 0; i < 1000000; i++) { decode(encoded); } console.timeEnd("decode emoji"); diff --git a/src/Encoder.ts b/src/Encoder.ts index b0636a7f..baf6063a 100644 --- a/src/Encoder.ts +++ b/src/Encoder.ts @@ -8,11 +8,15 @@ import { WASM_AVAILABLE, utf8EncodeWasm, WASM_STR_THRESHOLD } from "./wasmFuncti export const DEFAULT_MAX_DEPTH = 100; export const DEFAULT_INITIAL_BUFFER_SIZE = 2048; +const STR_CACHE_THRESHOLD = 32; + export class Encoder { private pos = 0; private view = new DataView(new ArrayBuffer(this.initialBufferSize)); private bytes = new Uint8Array(this.view.buffer); + private readonly strCache: Record = Object.create(null); + constructor( readonly extensionCodec = ExtensionCodec.defaultCodec, readonly maxDepth = DEFAULT_MAX_DEPTH, @@ -146,6 +150,16 @@ export class Encoder { const maxHeaderSize = 1 + 4; const strLength = object.length; + if (strLength < STR_CACHE_THRESHOLD) { + const buffer = this.strCache[object]; + if (buffer != null) { + this.writeStringHeader(buffer.byteLength); + this.bytes.set(buffer, this.pos); + this.pos += buffer.byteLength; + return; + } + } + if (WASM_AVAILABLE && strLength > WASM_STR_THRESHOLD) { // ensure max possible size const maxSize = maxHeaderSize + strLength * 4; @@ -154,12 +168,14 @@ export class Encoder { // utf8EncodeWasm() handles headByte+size as well as string itself const ouputLength = utf8EncodeWasm(object, this.bytes, this.pos); this.pos += ouputLength; - return; } else { const byteLength = utf8Count(object); this.ensureBufferSizeToWrite(maxHeaderSize + byteLength); this.writeStringHeader(byteLength); utf8Encode(object, this.bytes, this.pos); + if (byteLength < STR_CACHE_THRESHOLD) { + this.strCache[object] = this.bytes.subarray(this.pos, this.pos + byteLength); + } this.pos += byteLength; } }