You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-07 13:22:56 +03:00
Performance improvements and backpressure controls.
Simply and speed up command argument processing logic. Commands now return the true/false value from the underlying socket write(s). Implement command_queue high water and low water for more better control of queueing.
This commit is contained in:
@@ -35,8 +35,6 @@ function small_toString(buf, len) {
|
||||
|
||||
// Reset parser to it's original state.
|
||||
RedisReplyParser.prototype.reset = function () {
|
||||
this.state = "type";
|
||||
|
||||
this.return_buffer = new Buffer(16384); // for holding replies, might grow
|
||||
this.return_string = "";
|
||||
this.tmp_string = ""; // for holding size fields
|
||||
@@ -46,6 +44,22 @@ RedisReplyParser.prototype.reset = function () {
|
||||
this.multi_bulk_pos = 0;
|
||||
this.multi_bulk_nested_length = 0;
|
||||
this.multi_bulk_nested_replies = null;
|
||||
|
||||
this.states = {
|
||||
TYPE: 1,
|
||||
SINGLE_LINE: 2,
|
||||
MULTI_BULK_COUNT: 3,
|
||||
INTEGER_LINE: 4,
|
||||
BULK_LENGTH: 5,
|
||||
ERROR_LINE: 6,
|
||||
BULK_DATA: 7,
|
||||
UNKNOWN_TYPE: 8,
|
||||
FINAL_CR: 9,
|
||||
FINAL_LF: 10,
|
||||
MULTI_BULK_COUNT_LF: 11
|
||||
};
|
||||
|
||||
this.state = this.states.TYPE;
|
||||
};
|
||||
|
||||
RedisReplyParser.prototype.parser_error = function (message) {
|
||||
@@ -54,7 +68,7 @@ RedisReplyParser.prototype.parser_error = function (message) {
|
||||
};
|
||||
|
||||
RedisReplyParser.prototype.execute = function (incoming_buf) {
|
||||
var pos = 0, bd_tmp, bd_str, i, il;
|
||||
var pos = 0, bd_tmp, bd_str, i, il, states = this.states;
|
||||
//, state_times = {}, start_execute = new Date(), start_switch, end_switch, old_state;
|
||||
//start_switch = new Date();
|
||||
|
||||
@@ -63,76 +77,76 @@ RedisReplyParser.prototype.execute = function (incoming_buf) {
|
||||
// console.log("execute: " + this.state + ", " + pos + "/" + incoming_buf.length + ", " + String.fromCharCode(incoming_buf[pos]));
|
||||
|
||||
switch (this.state) {
|
||||
case "type":
|
||||
case states.TYPE:
|
||||
this.type = incoming_buf[pos];
|
||||
pos += 1;
|
||||
|
||||
switch (this.type) {
|
||||
case 43: // +
|
||||
this.state = "single line";
|
||||
this.state = states.SINGLE_LINE;
|
||||
this.return_buffer.end = 0;
|
||||
this.return_string = "";
|
||||
break;
|
||||
case 42: // *
|
||||
this.state = "multi bulk count";
|
||||
this.state = states.MULTI_BULK_COUNT;
|
||||
this.tmp_string = "";
|
||||
break;
|
||||
case 58: // :
|
||||
this.state = "integer line";
|
||||
this.state = states.INTEGER_LINE;
|
||||
this.return_buffer.end = 0;
|
||||
this.return_string = "";
|
||||
break;
|
||||
case 36: // $
|
||||
this.state = "bulk length";
|
||||
this.state = states.BULK_LENGTH;
|
||||
this.tmp_string = "";
|
||||
break;
|
||||
case 45: // -
|
||||
this.state = "error line";
|
||||
this.state = states.ERROR_LINE;
|
||||
this.return_buffer.end = 0;
|
||||
this.return_string = "";
|
||||
break;
|
||||
default:
|
||||
this.state = "unknown type";
|
||||
this.state = states.UNKNOWN_TYPE;
|
||||
}
|
||||
break;
|
||||
case "integer line":
|
||||
case states.INTEGER_LINE:
|
||||
if (incoming_buf[pos] === 13) {
|
||||
this.send_reply(+small_toString(this.return_buffer, this.return_buffer.end));
|
||||
this.state = "final lf";
|
||||
this.state = states.FINAL_LF;
|
||||
} else {
|
||||
this.return_buffer[this.return_buffer.end] = incoming_buf[pos];
|
||||
this.return_buffer.end += 1;
|
||||
}
|
||||
pos += 1;
|
||||
break;
|
||||
case "error line":
|
||||
case states.ERROR_LINE:
|
||||
if (incoming_buf[pos] === 13) {
|
||||
this.send_error(this.return_buffer.toString("ascii", 0, this.return_buffer.end));
|
||||
this.state = "final lf";
|
||||
this.state = states.FINAL_LF;
|
||||
} else {
|
||||
this.return_buffer[this.return_buffer.end] = incoming_buf[pos];
|
||||
this.return_buffer.end += 1;
|
||||
}
|
||||
pos += 1;
|
||||
break;
|
||||
case "single line":
|
||||
case states.SINGLE_LINE:
|
||||
if (incoming_buf[pos] === 13) {
|
||||
this.send_reply(this.return_string);
|
||||
this.state = "final lf";
|
||||
this.state = states.FINAL_LF;
|
||||
} else {
|
||||
this.return_string += String.fromCharCode(incoming_buf[pos]);
|
||||
}
|
||||
pos += 1;
|
||||
break;
|
||||
case "multi bulk count":
|
||||
case states.MULTI_BULK_COUNT:
|
||||
if (incoming_buf[pos] === 13) { // \r
|
||||
this.state = "multi bulk count lf";
|
||||
this.state = states.MULTI_BULK_COUNT_LF;
|
||||
} else {
|
||||
this.tmp_string += String.fromCharCode(incoming_buf[pos]);
|
||||
}
|
||||
pos += 1;
|
||||
break;
|
||||
case "multi bulk count lf":
|
||||
case states.MULTI_BULK_COUNT_LF:
|
||||
if (incoming_buf[pos] === 10) { // \n
|
||||
if (this.multi_bulk_length) { // nested multi-bulk
|
||||
this.multi_bulk_nested_length = this.multi_bulk_length;
|
||||
@@ -141,7 +155,7 @@ RedisReplyParser.prototype.execute = function (incoming_buf) {
|
||||
}
|
||||
this.multi_bulk_length = +this.tmp_string;
|
||||
this.multi_bulk_pos = 0;
|
||||
this.state = "type";
|
||||
this.state = states.TYPE;
|
||||
if (this.multi_bulk_length < 0) {
|
||||
this.send_reply(null);
|
||||
this.multi_bulk_length = 0;
|
||||
@@ -158,25 +172,25 @@ RedisReplyParser.prototype.execute = function (incoming_buf) {
|
||||
}
|
||||
pos += 1;
|
||||
break;
|
||||
case "bulk length":
|
||||
case states.BULK_LENGTH:
|
||||
if (incoming_buf[pos] === 13) { // \r
|
||||
this.state = "bulk lf";
|
||||
this.state = states.BULK_LF;
|
||||
} else {
|
||||
this.tmp_string += String.fromCharCode(incoming_buf[pos]);
|
||||
}
|
||||
pos += 1;
|
||||
break;
|
||||
case "bulk lf":
|
||||
case states.BULK_LF:
|
||||
if (incoming_buf[pos] === 10) { // \n
|
||||
this.bulk_length = +this.tmp_string;
|
||||
if (this.bulk_length === -1) {
|
||||
this.send_reply(null);
|
||||
this.state = "type";
|
||||
this.state = states.TYPE;
|
||||
} else if (this.bulk_length === 0) {
|
||||
this.send_reply(new Buffer(""));
|
||||
this.state = "final cr";
|
||||
this.state = states.FINAL_CR;
|
||||
} else {
|
||||
this.state = "bulk data";
|
||||
this.state = states.BULK_DATA;
|
||||
if (this.bulk_length > this.return_buffer.length) {
|
||||
if (exports.debug_mode) {
|
||||
console.log("Growing return_buffer from " + this.return_buffer.length + " to " + this.bulk_length);
|
||||
@@ -191,7 +205,7 @@ RedisReplyParser.prototype.execute = function (incoming_buf) {
|
||||
}
|
||||
pos += 1;
|
||||
break;
|
||||
case "bulk data":
|
||||
case states.BULK_DATA:
|
||||
this.return_buffer[this.return_buffer.end] = incoming_buf[pos];
|
||||
this.return_buffer.end += 1;
|
||||
pos += 1;
|
||||
@@ -206,21 +220,21 @@ RedisReplyParser.prototype.execute = function (incoming_buf) {
|
||||
}
|
||||
}
|
||||
this.send_reply(bd_tmp);
|
||||
this.state = "final cr";
|
||||
this.state = states.FINAL_CR;
|
||||
}
|
||||
break;
|
||||
case "final cr":
|
||||
case states.FINAL_CR:
|
||||
if (incoming_buf[pos] === 13) { // \r
|
||||
this.state = "final lf";
|
||||
this.state = states.FINAL_LF;
|
||||
pos += 1;
|
||||
} else {
|
||||
this.parser_error(new Error("saw " + incoming_buf[pos] + " when expecting final CR"));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case "final lf":
|
||||
case states.FINAL_LF:
|
||||
if (incoming_buf[pos] === 10) { // \n
|
||||
this.state = "type";
|
||||
this.state = states.TYPE;
|
||||
pos += 1;
|
||||
} else {
|
||||
this.parser_error(new Error("saw " + incoming_buf[pos] + " when expecting final LF"));
|
||||
|
Reference in New Issue
Block a user