Skip to content

Commit 0455504

Browse files
committed
fix: major performance issues with bytea performance brianc#2240
1 parent ea6ac2a commit 0455504

File tree

1 file changed

+35
-9
lines changed

1 file changed

+35
-9
lines changed

packages/pg-protocol/src/parser.ts

+35-9
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ export type MessageCallback = (msg: BackendMessage) => void
7575

7676
export class Parser {
7777
private remainingBuffer: Buffer = emptyBuffer
78+
private remainingBufferLength: number = 0
79+
private remainingBufferOffset: number = 0
7880
private reader = new BufferReader()
7981
private mode: Mode
8082

@@ -87,13 +89,33 @@ export class Parser {
8789

8890
public parse(buffer: Buffer, callback: MessageCallback) {
8991
let combinedBuffer = buffer
90-
if (this.remainingBuffer.byteLength) {
91-
combinedBuffer = Buffer.allocUnsafe(this.remainingBuffer.byteLength + buffer.byteLength)
92-
this.remainingBuffer.copy(combinedBuffer)
93-
buffer.copy(combinedBuffer, this.remainingBuffer.byteLength)
92+
let combinedBufferOffset = 0
93+
let combinedBufferLength = buffer.byteLength
94+
const newRealLength = this.remainingBufferLength + combinedBufferLength
95+
if (this.remainingBufferLength) {
96+
const newLength = newRealLength + this.remainingBufferOffset
97+
if (newLength > this.remainingBuffer.byteLength) {
98+
let newBufferLength = this.remainingBufferLength * 2
99+
while (newRealLength >= newBufferLength) {
100+
newBufferLength *= 2
101+
}
102+
const newBuffer = Buffer.allocUnsafe(newBufferLength)
103+
this.remainingBuffer.copy(
104+
newBuffer,
105+
0,
106+
this.remainingBufferOffset,
107+
this.remainingBufferOffset + this.remainingBufferLength
108+
)
109+
this.remainingBuffer = newBuffer
110+
this.remainingBufferOffset = 0
111+
}
112+
buffer.copy(this.remainingBuffer, this.remainingBufferOffset + this.remainingBufferLength)
113+
combinedBuffer = this.remainingBuffer
114+
combinedBufferLength = newRealLength
115+
combinedBufferOffset = this.remainingBufferOffset
94116
}
95-
let offset = 0
96-
while (offset + HEADER_LENGTH <= combinedBuffer.byteLength) {
117+
let offset = combinedBufferOffset
118+
while (offset + HEADER_LENGTH <= combinedBufferLength) {
97119
// code is 1 byte long - it identifies the message type
98120
const code = combinedBuffer[offset]
99121

@@ -102,7 +124,7 @@ export class Parser {
102124

103125
const fullMessageLength = CODE_LENGTH + length
104126

105-
if (fullMessageLength + offset <= combinedBuffer.byteLength) {
127+
if (fullMessageLength + offset <= combinedBufferLength) {
106128
const message = this.handlePacket(offset + HEADER_LENGTH, code, length, combinedBuffer)
107129
callback(message)
108130
offset += fullMessageLength
@@ -111,10 +133,14 @@ export class Parser {
111133
}
112134
}
113135

114-
if (offset === combinedBuffer.byteLength) {
136+
if (offset === combinedBufferLength) {
115137
this.remainingBuffer = emptyBuffer
138+
this.remainingBufferLength = 0
139+
this.remainingBufferOffset = 0
116140
} else {
117-
this.remainingBuffer = combinedBuffer.slice(offset)
141+
this.remainingBuffer = combinedBuffer
142+
this.remainingBufferLength = combinedBufferLength - offset
143+
this.remainingBufferOffset += offset
118144
}
119145
}
120146

0 commit comments

Comments
 (0)