Skip to content

Commit 658c79d

Browse files
author
Ruben Bridgewater
committed
fix(jsparser): Parsing time for big nested arrays is now linear
1 parent e44ea96 commit 658c79d

File tree

3 files changed

+47
-21
lines changed

3 files changed

+47
-21
lines changed

benchmark/index.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ for (i = 0; i < arraySize; i++) {
6363
var arrayBuffer = new Buffer(array)
6464

6565
var bigArraySize = 1000
66-
var bigArrayChunks = [new Buffer('*' + bigArraySize * 2)]
66+
var bigArrayChunks = [new Buffer('*1\r\n*1\r\n*' + bigArraySize * 2)]
6767
for (i = 0; i < bigArraySize; i++) {
6868
size = (Math.random() * 10000 | 0)
6969
if (i % 2) {
@@ -251,27 +251,27 @@ suite.add('JS PARSER BUF: * array', function () {
251251
parserBuffer.execute(arrayBuffer)
252252
})
253253

254-
// BIG ARRAYS
254+
// BIG NESTED ARRAYS
255255

256-
suite.add('\nHIREDIS: * big array', function () {
256+
suite.add('\nHIREDIS: * big nested array', function () {
257257
for (var i = 0; i < bigArrayChunks.length; i++) {
258258
parserHiRedis.execute(bigArrayChunks[i])
259259
}
260260
})
261261

262-
suite.add('HIREDIS BUF: * big array', function () {
262+
suite.add('HIREDIS BUF: * big nested array', function () {
263263
for (var i = 0; i < bigArrayChunks.length; i++) {
264264
parserHiRedisBuffer.execute(bigArrayChunks[i])
265265
}
266266
})
267267

268-
suite.add('JS PARSER: * big array', function () {
268+
suite.add('JS PARSER: * big nested array', function () {
269269
for (var i = 0; i < bigArrayChunks.length; i++) {
270270
parser.execute(bigArrayChunks[i])
271271
}
272272
})
273273

274-
suite.add('JS PARSER BUF: * big array', function () {
274+
suite.add('JS PARSER BUF: * big nested array', function () {
275275
for (var i = 0; i < bigArrayChunks.length; i++) {
276276
parserBuffer.execute(bigArrayChunks[i])
277277
}

changelog.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## v.2.4.0 - xx Jan, 2017
2+
3+
Bugfixes
4+
5+
- Parsing time for big nested arrays is now linear
6+
17
## v.2.3.0 - 25 Nov, 2016
28

39
Features

lib/parser.js

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -209,13 +209,36 @@ function parseArray (parser) {
209209
return parseArrayElements(parser, responses, 0)
210210
}
211211

212+
/**
213+
* Push a partly parsed array to the stack
214+
*
215+
* @param parser
216+
* @param elem
217+
* @param i
218+
* @returns {undefined}
219+
*/
220+
function pushArrayCache (parser, elem, pos) {
221+
parser.arrayCache.push(elem)
222+
parser.arrayPos.push(pos)
223+
}
224+
212225
/**
213226
* Parse chunked redis array response
214227
* @param parser
215228
* @returns {*}
216229
*/
217230
function parseArrayChunks (parser) {
218-
return parseArrayElements(parser, parser.arrayCache, parser.arrayPos)
231+
var tmp = parser.arrayCache.pop()
232+
var pos = parser.arrayPos.pop()
233+
if (parser.arrayCache.length) {
234+
var res = parseArrayChunks(parser)
235+
if (!res) {
236+
pushArrayCache(parser, tmp, pos)
237+
return
238+
}
239+
tmp[pos++] = res
240+
}
241+
return parseArrayElements(parser, tmp, pos)
219242
}
220243

221244
/**
@@ -230,16 +253,15 @@ function parseArrayElements (parser, responses, i) {
230253
while (i < responses.length) {
231254
var offset = parser.offset
232255
if (parser.offset >= bufferLength) {
233-
parser.arrayCache = responses
234-
parser.arrayPos = i
235-
parser.offset = offset
256+
pushArrayCache(parser, responses, i)
236257
return
237258
}
238259
var response = parseType(parser, parser.buffer[parser.offset++])
239260
if (response === undefined) {
240-
parser.arrayCache = responses
241-
parser.arrayPos = i
242-
parser.offset = offset
261+
if (!parser.arrayCache.length) {
262+
parser.offset = offset
263+
}
264+
pushArrayCache(parser, responses, i)
243265
return
244266
}
245267
responses[i] = response
@@ -324,8 +346,8 @@ function JavascriptRedisParser (options) {
324346
this.bigOffset = 0
325347
this.totalChunkSize = 0
326348
this.bufferCache = []
327-
this.arrayCache = null
328-
this.arrayPos = 0
349+
this.arrayCache = []
350+
this.arrayPos = []
329351
}
330352

331353
/**
@@ -439,31 +461,29 @@ JavascriptRedisParser.prototype.execute = function execute (buffer) {
439461
buffer.copy(newBuffer, remainingLength, 0, buffer.length)
440462
this.buffer = newBuffer
441463
this.offset = 0
442-
if (this.arrayCache) {
464+
if (this.arrayCache.length) {
443465
arr = parseArrayChunks(this)
444466
if (!arr) {
445467
return
446468
}
447469
this.returnReply(arr)
448-
this.arrayCache = null
449470
}
450471
} else if (this.totalChunkSize + buffer.length >= this.bigStrSize) {
451472
this.bufferCache.push(buffer)
452-
if (this.optionReturnBuffers === false && !this.arrayCache) {
473+
if (this.optionReturnBuffers === false && !this.arrayCache.length) {
453474
this.returnReply(concatBulkString(this))
454475
this.buffer = buffer
455476
} else {
456477
this.buffer = concatBuffer(this, this.totalChunkSize + buffer.length)
457478
this.offset = 0
458-
if (this.arrayCache) {
479+
if (this.arrayCache.length) {
459480
arr = parseArrayChunks(this)
460481
if (!arr) {
461482
this.bigStrSize = 0
462483
this.bufferCache = []
463484
return
464485
}
465486
this.returnReply(arr)
466-
this.arrayCache = null
467487
}
468488
}
469489
this.bigStrSize = 0
@@ -479,7 +499,7 @@ JavascriptRedisParser.prototype.execute = function execute (buffer) {
479499
var type = this.buffer[this.offset++]
480500
var response = parseType(this, type)
481501
if (response === undefined) {
482-
if (!this.arrayCache) {
502+
if (!this.arrayCache.length) {
483503
this.offset = offset
484504
}
485505
return

0 commit comments

Comments
 (0)