Skip to content

Commit 55310e1

Browse files
committed
Reuse buffer after socket's done writing (if applicable)
1 parent 27cb98e commit 55310e1

File tree

3 files changed

+34
-17
lines changed

3 files changed

+34
-17
lines changed

CHANGES.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
In next release ...
22

3+
- Reduce buffer allocation and intelligently scale initial allocation when creating
4+
a new buffer.
5+
36
- Both the `Query` object and client configuration now provide an optional `bigints`
47
setting which decides whether to use bigints or the number type for the INT8
58
data type. The setting is enabled by default.

src/buffer.ts

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1+
const INITIAL_SIZE = 4096;
2+
13
export class ElasticBuffer {
24
private offset = 0;
3-
private buffer: Buffer;
4-
5-
constructor(size: number) {
6-
this.buffer = Buffer.allocUnsafe(size);
7-
}
5+
private buffer?: Buffer;
6+
private size = INITIAL_SIZE;
87

98
clear() {
109
this.offset = 0;
@@ -15,30 +14,42 @@ export class ElasticBuffer {
1514
}
1615

1716
reserve(size: number) {
18-
let length = this.buffer.length;
17+
let length = this.buffer?.length || 0;
1918
const offset = this.offset;
2019
const available = length - offset;
2120

22-
if (available < size) {
23-
while (available + length < size) length *= 2;
24-
const buffer = Buffer.allocUnsafe(length * 2);
25-
this.buffer.copy(buffer, 0, 0, offset);
21+
if (available < size || !this.buffer) {
22+
while (available + length < size) length = Math.max(this.size, length << 1);
23+
const buffer = Buffer.allocUnsafe(length << 1);
24+
if (this.buffer) {
25+
this.buffer.copy(buffer, 0, 0, offset);
26+
}
2627
this.buffer = buffer;
28+
return buffer;
2729
}
30+
return this.buffer;
2831
}
2932

3033
getBuffer(size: number) {
3134
const offset = this.offset;
32-
this.reserve(size);
35+
const buffer = this.reserve(size);
3336
this.offset += size;
34-
return this.buffer.subarray(offset, offset + size);
37+
return buffer.subarray(offset, offset + size);
3538
}
3639

3740
consume() {
38-
const end = this.offset;
39-
const buffer = Buffer.allocUnsafe(end);
40-
this.buffer.copy(buffer, 0, 0, end);
41+
const buffer = this.buffer?.subarray(0, this.offset);
42+
if (buffer) {
43+
this.size = Math.max(this.offset, INITIAL_SIZE) >> 1;
44+
}
4145
this.offset = 0;
46+
this.buffer = undefined;
4247
return buffer;
4348
}
49+
50+
offer(buffer: Buffer) {
51+
if (!this.buffer) {
52+
this.buffer = buffer;
53+
}
54+
}
4455
}

src/protocol.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,7 @@ export class Reader {
659659
}
660660

661661
export class Writer {
662-
private outgoing: ElasticBuffer = new ElasticBuffer(4096);
662+
private outgoing: ElasticBuffer = new ElasticBuffer();
663663

664664
constructor(private readonly encoding: BufferEncoding) { }
665665

@@ -1085,7 +1085,10 @@ export class Writer {
10851085
send(socket: Socket) {
10861086
if (this.outgoing.empty) return;
10871087
const buffer = this.outgoing.consume();
1088-
return socket.write(buffer);
1088+
if (buffer) {
1089+
return socket.write(buffer, () => this.outgoing.offer(buffer));
1090+
}
1091+
return true;
10891092
}
10901093

10911094
startup(settings: StartupConfiguration) {

0 commit comments

Comments
 (0)