diff --git a/lib/eventsource.js b/lib/eventsource.js index a81381d..686c0be 100644 --- a/lib/eventsource.js +++ b/lib/eventsource.js @@ -15,6 +15,8 @@ var colon = 58 var space = 32 var lineFeed = 10 var carriageReturn = 13 +// Beyond 256KB we could not observe any gain in performance +var maxBufferAheadAllocation = 1024 * 256 function hasBom (buf) { return bom.every(function (charCode, index) { @@ -179,19 +181,36 @@ function EventSource (url, eventSourceInitDict) { // text/event-stream parser adapted from webkit's // Source/WebCore/page/EventSource.cpp - var isFirst = true var buf + var newBuffer var startingPos = 0 var startingFieldLength = -1 + var newBufferSize = 0 + var bytesUsed = 0 + res.on('data', function (chunk) { - buf = buf ? Buffer.concat([buf, chunk]) : chunk - if (isFirst && hasBom(buf)) { - buf = buf.slice(bom.length) + if (!buf) { + buf = chunk + if (hasBom(buf)) { + buf = buf.slice(bom.length) + } + bytesUsed = buf.length + } else { + if (chunk.length > buf.length - bytesUsed) { + newBufferSize = (buf.length * 2) + chunk.length + if (newBufferSize > maxBufferAheadAllocation) { + newBufferSize = buf.length + chunk.length + maxBufferAheadAllocation + } + newBuffer = Buffer.alloc(newBufferSize) + buf.copy(newBuffer, 0, 0, bytesUsed) + buf = newBuffer + } + chunk.copy(buf, bytesUsed) + bytesUsed += chunk.length } - isFirst = false var pos = 0 - var length = buf.length + var length = bytesUsed while (pos < length) { if (discardTrailingNewline) { @@ -235,8 +254,10 @@ function EventSource (url, eventSourceInitDict) { if (pos === length) { buf = void 0 + bytesUsed = 0 } else if (pos > 0) { - buf = buf.slice(pos) + buf = buf.slice(pos, bytesUsed) + bytesUsed = buf.length } }) }) diff --git a/test/eventsource_test.js b/test/eventsource_test.js index b0be4ec..31f6eea 100644 --- a/test/eventsource_test.js +++ b/test/eventsource_test.js @@ -454,7 +454,7 @@ describe('Parser', function () { }) it('parses relatively huge messages efficiently', function (done) { - this.timeout(1000) + this.timeout(200) createServer(function (err, server) { if (err) return done(err)