Skip to content

Commit 931ac21

Browse files
perf(encoding): optimize StringEncoder with direct encodeInto
1 parent 5946d67 commit 931ac21

2 files changed

Lines changed: 7 additions & 19 deletions

File tree

.jules/bolt.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
## 2026-01-19 - Avoid Intermediate Buffers with TextEncoder
2+
**Learning:** TextEncoder.encodeInto works directly with Uint8Array views on SharedArrayBuffer. Intermediate buffers and copying are unnecessary and can double the execution time.
3+
**Action:** Check TextEncoder usage for direct writing to destination buffers.

src/encoding/StringEncoder.ts

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,20 @@
11
import Serializable from "./Serializable";
22

33
export default class StringEncoder implements Serializable<string> {
4-
// Default size of the decoder buffer that's always reused (in bytes)
5-
private static readonly ENCODER_BUFFER_SIZE = 16384
6-
74
private textEncoder = new TextEncoder();
85
private textDecoder = new TextDecoder();
96

10-
private encoderBuffer: ArrayBuffer = new ArrayBuffer(StringEncoder.ENCODER_BUFFER_SIZE);
11-
private encoderArray: Uint8Array = new Uint8Array(this.encoderBuffer);
12-
private currentDecoderBufferSize: number = StringEncoder.ENCODER_BUFFER_SIZE;
13-
147
decode(buffer: Uint8Array): string {
158
return this.textDecoder.decode(buffer);
169
}
1710

1811
encode(stringValue: string, destination: Uint8Array): number {
1912
// Safari does not support the encodeInto function
2013
if (this.textEncoder.encodeInto !== undefined) {
21-
const maxStringLength = stringValue.length * 3;
22-
23-
if (this.currentDecoderBufferSize < maxStringLength) {
24-
this.encoderBuffer = new ArrayBuffer(maxStringLength);
25-
this.encoderArray = new Uint8Array(this.encoderBuffer);
26-
this.currentDecoderBufferSize = maxStringLength;
27-
}
28-
29-
const writeResult = this.textEncoder.encodeInto(stringValue, this.encoderArray);
30-
const writeLength = writeResult.written || 0;
31-
destination.set(this.encoderArray.subarray(0, writeLength));
32-
return writeLength;
14+
// Optimization: Write directly to destination to avoid intermediate buffer and copy.
15+
// destination is guaranteed to be large enough (max string length * 3) by the caller (ShareableArray).
16+
const writeResult = this.textEncoder.encodeInto(stringValue, destination);
17+
return writeResult.written || 0;
3318
} else {
3419
const encodedString = this.textEncoder.encode(stringValue);
3520
destination.set(encodedString);

0 commit comments

Comments
 (0)