From bde8a92865dcbe546f6800ec53ad3efbfba46b2a Mon Sep 17 00:00:00 2001 From: Weijia Wang Date: Fri, 8 Feb 2019 13:53:57 +0800 Subject: [PATCH 1/2] http: reduce multiple output arrays into one Now we are using `output`, `outputEncodings` and `outputCallbacks` to hold pending data. Reducing them into one array `outputData` can slightly improve performance and reduce some redundant codes. --- lib/_http_client.js | 6 +-- lib/_http_outgoing.js | 45 +++++++++---------- .../test-http-destroyed-socket-write2.js | 3 +- 3 files changed, 24 insertions(+), 30 deletions(-) diff --git a/lib/_http_client.js b/lib/_http_client.js index 1ccb289b24791a..7379e2ee6dee87 100644 --- a/lib/_http_client.js +++ b/lib/_http_client.js @@ -374,10 +374,8 @@ function socketCloseListener() { // Too bad. That output wasn't getting written. // This is pretty terrible that it doesn't raise an error. // Fixed better in v0.10 - if (req.output) - req.output.length = 0; - if (req.outputEncodings) - req.outputEncodings.length = 0; + if (req.outputData) + req.outputData.length = 0; if (parser) { parser.finish(); diff --git a/lib/_http_outgoing.js b/lib/_http_outgoing.js index d89a34e664fe6b..b93a31abacf0b0 100644 --- a/lib/_http_outgoing.js +++ b/lib/_http_outgoing.js @@ -70,9 +70,7 @@ function OutgoingMessage() { // Queue that holds all currently pending data, until the response will be // assigned to the socket (until it will its turn in the HTTP pipeline). - this.output = []; - this.outputEncodings = []; - this.outputCallbacks = []; + this.outputData = []; // `outputSize` is an approximate measure of how much data is queued on this // response. `_onPendingData` will be invoked to update similar global @@ -220,14 +218,18 @@ OutgoingMessage.prototype._send = function _send(data, encoding, callback) { data = this._header + data; } else { var header = this._header; - if (this.output.length === 0) { - this.output = [header]; - this.outputEncodings = ['latin1']; - this.outputCallbacks = [null]; + if (this.outputData.length === 0) { + this.outputData = [{ + data: header, + encoding: 'latin1', + callback: null + }]; } else { - this.output.unshift(header); - this.outputEncodings.unshift('latin1'); - this.outputCallbacks.unshift(null); + this.outputData.unshift({ + data: header, + encoding: 'latin1', + callback: null + }); } this.outputSize += header.length; this._onPendingData(header.length); @@ -254,7 +256,7 @@ function _writeRaw(data, encoding, callback) { if (conn && conn._httpMessage === this && conn.writable && !conn.destroyed) { // There might be pending data in the this.output buffer. - if (this.output.length) { + if (this.outputData.length) { this._flushOutput(conn); } else if (!data.length) { if (typeof callback === 'function') { @@ -273,9 +275,7 @@ function _writeRaw(data, encoding, callback) { return conn.write(data, encoding, callback); } // Buffer, as long as we're not destroyed. - this.output.push(data); - this.outputEncodings.push(encoding); - this.outputCallbacks.push(callback); + this.outputData.push({ data, encoding, callback }); this.outputSize += data.length; this._onPendingData(data.length); return false; @@ -738,7 +738,7 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) { // There is the first message on the outgoing queue, and we've sent // everything to the socket. debug('outgoing message end.'); - if (this.output.length === 0 && + if (this.outputData.length === 0 && this.connection && this.connection._httpMessage === this) { this._finish(); @@ -793,22 +793,19 @@ OutgoingMessage.prototype._flush = function _flush() { OutgoingMessage.prototype._flushOutput = function _flushOutput(socket) { var ret; - var outputLength = this.output.length; + var outputLength = this.outputData.length; if (outputLength <= 0) return ret; - var output = this.output; - var outputEncodings = this.outputEncodings; - var outputCallbacks = this.outputCallbacks; + var outputData = this.outputData; socket.cork(); - for (var i = 0; i < outputLength; i++) { - ret = socket.write(output[i], outputEncodings[i], outputCallbacks[i]); + for (var i = 0; i < outputData.length; i++) { + const { data, encoding, callback } = outputData[i]; + ret = socket.write(data, encoding, callback); } socket.uncork(); - this.output = []; - this.outputEncodings = []; - this.outputCallbacks = []; + this.outputData = []; this._onPendingData(-this.outputSize); this.outputSize = 0; diff --git a/test/parallel/test-http-destroyed-socket-write2.js b/test/parallel/test-http-destroyed-socket-write2.js index 48899415e37a4f..551cea19829d93 100644 --- a/test/parallel/test-http-destroyed-socket-write2.js +++ b/test/parallel/test-http-destroyed-socket-write2.js @@ -69,8 +69,7 @@ server.listen(0, function() { } - assert.strictEqual(req.output.length, 0); - assert.strictEqual(req.outputEncodings.length, 0); + assert.strictEqual(req.outputData.length, 0); server.close(); })); From 89a723cb6cc75be0085e6c63fa6f2bbd7095a99a Mon Sep 17 00:00:00 2001 From: Weijia Wang <381152119@qq.com> Date: Sat, 9 Feb 2019 09:16:18 +0800 Subject: [PATCH 2/2] [squash] using outputLength --- lib/_http_outgoing.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/_http_outgoing.js b/lib/_http_outgoing.js index b93a31abacf0b0..40a09eeec08d7a 100644 --- a/lib/_http_outgoing.js +++ b/lib/_http_outgoing.js @@ -799,7 +799,7 @@ OutgoingMessage.prototype._flushOutput = function _flushOutput(socket) { var outputData = this.outputData; socket.cork(); - for (var i = 0; i < outputData.length; i++) { + for (var i = 0; i < outputLength; i++) { const { data, encoding, callback } = outputData[i]; ret = socket.write(data, encoding, callback); }