1
0
mirror of https://github.com/redis/node-redis.git synced 2025-08-06 02:15:48 +03:00

Intermediate fix js parser handling big values very slow

Closes #900
This commit is contained in:
Ruben Bridgewater
2015-11-08 23:05:15 +01:00
parent c08461f781
commit ff857f97ae
4 changed files with 44 additions and 30 deletions

View File

@@ -1,6 +1,13 @@
Changelog Changelog
========= =========
## v.2.3.1 - xx Nov, 2015
Bugfixes
- Fixed js parser handling big values very slow ([@BridgeAR](https://github.com/BridgeAR))
- The speed is up to ~500% faster than before but still up to ~50% slower than the hiredis parser.
## v.2.3.0 - 30 Oct, 2015 ## v.2.3.0 - 30 Oct, 2015
Features Features

View File

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

View File

@@ -1,11 +1,12 @@
'use strict'; 'use strict';
var util = require('util'); var util = require('util');
function JavascriptReplyParser() { function JavascriptReplyParser() {
this.name = exports.name; this.name = exports.name;
this._buffer = new Buffer(0); this._buffer = new Buffer(0);
this._offset = 0; this._offset = 0;
this._buffers = [];
} }
function IncompleteReadBuffer(message) { function IncompleteReadBuffer(message) {
@@ -66,7 +67,7 @@ JavascriptReplyParser.prototype._parseResult = function (type) {
return null; return null;
} }
if (packetHeader > this._bytesRemaining()) { if (packetHeader > this._buffer.length - this._offset) {
this._offset = offset - 1; this._offset = offset - 1;
throw new IncompleteReadBuffer('Wait for more data.'); throw new IncompleteReadBuffer('Wait for more data.');
} }
@@ -93,14 +94,37 @@ JavascriptReplyParser.prototype._parseResult = function (type) {
}; };
JavascriptReplyParser.prototype.execute = function (buffer) { JavascriptReplyParser.prototype.execute = function (buffer) {
this.append(buffer); var i = buffer.length - 1;
var type, offset; while (buffer[i] !== 0x0a) {
i--;
if (i < 1) {
this._buffers.push(buffer);
return;
}
}
if (this._buffers.length !== 0) {
this._buffers.unshift(this._offset === 0 ? this._buffer : this._buffer.slice(this._offset));
this._buffers.push(buffer);
this._buffer = Buffer.concat(this._buffers);
this._buffers = [];
} else if (this._offset >= this._buffer.length) {
this._buffer = buffer;
} else {
this._buffer = Buffer.concat([this._buffer.slice(this._offset), buffer]);
}
this._offset = 0;
this.run();
};
JavascriptReplyParser.prototype.run = function (buffer) {
var type, offset = this._offset;
while (true) { while (true) {
offset = this._offset; offset = this._offset;
// at least 4 bytes: :1\r\n // at least 4 bytes: :1\r\n
if (this._bytesRemaining() < 4) { if (this._buffer.length - this._offset < 4) {
break; break;
} }
@@ -109,7 +133,7 @@ JavascriptReplyParser.prototype.execute = function (buffer) {
if (type === 43 || type === 58 || type === 36) { // Strings + // Integers : // Bulk strings $ if (type === 43 || type === 58 || type === 36) { // Strings + // Integers : // Bulk strings $
this.send_reply(this._parseResult(type)); this.send_reply(this._parseResult(type));
} else if (type === 45) { // Errors - } else if (type === 45) { // Errors -
this.send_error(this._parseResult(type)); this.send_error(this._parseResult(type));
} else if (type === 42) { // Arrays * } else if (type === 42) { // Arrays *
// set a rewind point. if a failure occurs, // set a rewind point. if a failure occurs,
@@ -130,24 +154,11 @@ JavascriptReplyParser.prototype.execute = function (buffer) {
} }
}; };
JavascriptReplyParser.prototype.append = function (newBuffer) {
// out of data
if (this._offset >= this._buffer.length) {
this._buffer = newBuffer;
this._offset = 0;
return;
}
this._buffer = Buffer.concat([this._buffer.slice(this._offset), newBuffer]);
this._offset = 0;
};
JavascriptReplyParser.prototype.parseHeader = function () { JavascriptReplyParser.prototype.parseHeader = function () {
var end = this._packetEndOffset() + 1, var end = this._packetEndOffset(),
value = this._buffer.toString('ascii', this._offset, end - 1) | 0; value = this._buffer.toString('ascii', this._offset, end) | 0;
this._offset = end + 1; this._offset = end + 2;
return value; return value;
}; };
@@ -167,9 +178,5 @@ JavascriptReplyParser.prototype._packetEndOffset = function () {
return offset; return offset;
}; };
JavascriptReplyParser.prototype._bytesRemaining = function () {
return (this._buffer.length - this._offset) < 0 ? 0 : (this._buffer.length - this._offset);
};
exports.Parser = JavascriptReplyParser; exports.Parser = JavascriptReplyParser;
exports.name = 'javascript'; exports.name = 'javascript';

View File

@@ -261,7 +261,7 @@ describe("return_buffers", function () {
} }
}); });
}); });
it('receives buffer messages', function (done) { it('receives buffer messages', function (done) {
sub.on("subscribe", function (chnl, count) { sub.on("subscribe", function (chnl, count) {
pub.publish(channel, message); pub.publish(channel, message);