Skip to content

Commit ff857f9

Browse files
author
Ruben Bridgewater
committed
Intermediate fix js parser handling big values very slow
Closes #900
1 parent c08461f commit ff857f9

File tree

4 files changed

+44
-30
lines changed

4 files changed

+44
-30
lines changed

changelog.md

+7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
Changelog
22
=========
33

4+
## v.2.3.1 - xx Nov, 2015
5+
6+
Bugfixes
7+
8+
- Fixed js parser handling big values very slow ([@BridgeAR](https://github.com/BridgeAR))
9+
- The speed is up to ~500% faster than before but still up to ~50% slower than the hiredis parser.
10+
411
## v.2.3.0 - 30 Oct, 2015
512

613
Features

index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -733,7 +733,7 @@ RedisClient.prototype.send_command = function (command, args, callback) {
733733
buffer_args = true;
734734
} else if (typeof args[i] !== 'string') {
735735
args[i] = String(args[i]);
736-
// 30000 seemed to be a good value to switch to buffers after testing this with and checking the pros and cons
736+
// 30000 seemed to be a good value to switch to buffers after testing and checking the pros and cons
737737
} else if (args[i].length > 30000) {
738738
big_data = true;
739739
args[i] = new Buffer(args[i]);

lib/parsers/javascript.js

+35-28
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
'use strict';
22

3-
var util = require('util');
3+
var util = require('util');
44

55
function JavascriptReplyParser() {
66
this.name = exports.name;
7-
this._buffer = new Buffer(0);
8-
this._offset = 0;
7+
this._buffer = new Buffer(0);
8+
this._offset = 0;
9+
this._buffers = [];
910
}
1011

1112
function IncompleteReadBuffer(message) {
@@ -66,7 +67,7 @@ JavascriptReplyParser.prototype._parseResult = function (type) {
6667
return null;
6768
}
6869

69-
if (packetHeader > this._bytesRemaining()) {
70+
if (packetHeader > this._buffer.length - this._offset) {
7071
this._offset = offset - 1;
7172
throw new IncompleteReadBuffer('Wait for more data.');
7273
}
@@ -93,14 +94,37 @@ JavascriptReplyParser.prototype._parseResult = function (type) {
9394
};
9495

9596
JavascriptReplyParser.prototype.execute = function (buffer) {
96-
this.append(buffer);
97+
var i = buffer.length - 1;
98+
99+
while (buffer[i] !== 0x0a) {
100+
i--;
101+
if (i < 1) {
102+
this._buffers.push(buffer);
103+
return;
104+
}
105+
}
106+
107+
if (this._buffers.length !== 0) {
108+
this._buffers.unshift(this._offset === 0 ? this._buffer : this._buffer.slice(this._offset));
109+
this._buffers.push(buffer);
110+
this._buffer = Buffer.concat(this._buffers);
111+
this._buffers = [];
112+
} else if (this._offset >= this._buffer.length) {
113+
this._buffer = buffer;
114+
} else {
115+
this._buffer = Buffer.concat([this._buffer.slice(this._offset), buffer]);
116+
}
117+
this._offset = 0;
118+
this.run();
119+
};
97120

98-
var type, offset;
121+
JavascriptReplyParser.prototype.run = function (buffer) {
122+
var type, offset = this._offset;
99123

100124
while (true) {
101125
offset = this._offset;
102126
// at least 4 bytes: :1\r\n
103-
if (this._bytesRemaining() < 4) {
127+
if (this._buffer.length - this._offset < 4) {
104128
break;
105129
}
106130

@@ -109,7 +133,7 @@ JavascriptReplyParser.prototype.execute = function (buffer) {
109133

110134
if (type === 43 || type === 58 || type === 36) { // Strings + // Integers : // Bulk strings $
111135
this.send_reply(this._parseResult(type));
112-
} else if (type === 45) { // Errors -
136+
} else if (type === 45) { // Errors -
113137
this.send_error(this._parseResult(type));
114138
} else if (type === 42) { // Arrays *
115139
// set a rewind point. if a failure occurs,
@@ -130,24 +154,11 @@ JavascriptReplyParser.prototype.execute = function (buffer) {
130154
}
131155
};
132156

133-
JavascriptReplyParser.prototype.append = function (newBuffer) {
134-
135-
// out of data
136-
if (this._offset >= this._buffer.length) {
137-
this._buffer = newBuffer;
138-
this._offset = 0;
139-
return;
140-
}
141-
142-
this._buffer = Buffer.concat([this._buffer.slice(this._offset), newBuffer]);
143-
this._offset = 0;
144-
};
145-
146157
JavascriptReplyParser.prototype.parseHeader = function () {
147-
var end = this._packetEndOffset() + 1,
148-
value = this._buffer.toString('ascii', this._offset, end - 1) | 0;
158+
var end = this._packetEndOffset(),
159+
value = this._buffer.toString('ascii', this._offset, end) | 0;
149160

150-
this._offset = end + 1;
161+
this._offset = end + 2;
151162

152163
return value;
153164
};
@@ -167,9 +178,5 @@ JavascriptReplyParser.prototype._packetEndOffset = function () {
167178
return offset;
168179
};
169180

170-
JavascriptReplyParser.prototype._bytesRemaining = function () {
171-
return (this._buffer.length - this._offset) < 0 ? 0 : (this._buffer.length - this._offset);
172-
};
173-
174181
exports.Parser = JavascriptReplyParser;
175182
exports.name = 'javascript';

test/return_buffers.spec.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ describe("return_buffers", function () {
261261
}
262262
});
263263
});
264-
264+
265265
it('receives buffer messages', function (done) {
266266
sub.on("subscribe", function (chnl, count) {
267267
pub.publish(channel, message);

0 commit comments

Comments
 (0)