Skip to content

Commit f9466b4

Browse files
committed
Remove unnecessary buffer copies when receiving large packets
1 parent 7ae7635 commit f9466b4

File tree

2 files changed

+46
-10
lines changed

2 files changed

+46
-10
lines changed

Changes.md

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ you spot any mistakes.
1212
* Add new error codes up to MySQL 5.7.17
1313
* Fix edge cases when determing Query result packets #1547
1414
* Fix memory leak when using long-running domains #1619 #1620
15+
* Remove unnecessary buffer copies when receiving large packets
1516
* Update `bignumber.js` to 3.1.2
1617
* Use a simple buffer list to improve performance #566 #1590
1718

lib/protocol/Parser.js

+45-10
Original file line numberDiff line numberDiff line change
@@ -100,20 +100,47 @@ Parser.prototype.append = function append(chunk) {
100100
return;
101101
}
102102

103-
var buffer = chunk;
103+
// Calculate slice ranges
104104
var sliceEnd = this._buffer.length;
105105
var sliceStart = this._packetOffset === null
106106
? this._offset
107107
: this._packetOffset;
108108
var sliceLength = sliceEnd - sliceStart;
109109

110+
// Get chunk data
111+
var buffer = null;
112+
var chunks = !(chunk instanceof Array || Array.isArray(chunk)) ? [chunk] : chunk;
113+
var length = 0;
114+
var offset = 0;
115+
116+
for (var i = 0; i < chunks.length; i++) {
117+
length += chunks[i].length;
118+
}
119+
110120
if (sliceLength !== 0) {
111121
// Create a new Buffer
112-
buffer = new Buffer(sliceLength + chunk.length);
122+
buffer = new Buffer(sliceLength + length);
123+
offset = 0;
124+
125+
// Copy data slice
126+
offset += this._buffer.copy(buffer, 0, sliceStart, sliceEnd);
113127

114-
// Copy data
115-
this._buffer.copy(buffer, 0, sliceStart, sliceEnd);
116-
chunk.copy(buffer, sliceLength);
128+
// Copy chunks
129+
for (var i = 0; i < chunks.length; i++) {
130+
offset += chunks[i].copy(buffer, offset);
131+
}
132+
} else if (chunks.length > 1) {
133+
// Create a new Buffer
134+
buffer = new Buffer(length);
135+
offset = 0;
136+
137+
// Copy chunks
138+
for (var i = 0; i < chunks.length; i++) {
139+
offset += chunks[i].copy(buffer, offset);
140+
}
141+
} else {
142+
// Buffer is the only chunk
143+
buffer = chunks[0];
117144
}
118145

119146
// Adjust data-tracking pointers
@@ -384,19 +411,27 @@ Parser.prototype.packetLength = function packetLength() {
384411
};
385412

386413
Parser.prototype._combineNextBuffers = function _combineNextBuffers(bytes) {
387-
if ((this._buffer.length - this._offset) >= bytes) {
414+
var length = this._buffer.length - this._offset;
415+
416+
if (length >= bytes) {
388417
return true;
389418
}
390419

391-
if (!this._nextBuffers.size) {
420+
if ((length + this._nextBuffers.size) < bytes) {
392421
return false;
393422
}
394423

395-
while (this._nextBuffers.size && (this._buffer.length - this._offset) < bytes) {
396-
this.append(this._nextBuffers.shift());
424+
var buffers = [];
425+
var bytesNeeded = bytes - length;
426+
427+
while (bytesNeeded > 0) {
428+
var buffer = this._nextBuffers.shift();
429+
buffers.push(buffer);
430+
bytesNeeded -= buffer.length;
397431
}
398432

399-
return (this._buffer.length - this._offset) >= bytes;
433+
this.append(buffers);
434+
return true;
400435
};
401436

402437
Parser.prototype._combineLongPacketBuffers = function _combineLongPacketBuffers() {

0 commit comments

Comments
 (0)