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.

PR-URL: https://github.com/nodejs/node/pull/26004
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Minwoo Jung <minwoo@nodesource.com>
This commit is contained in:
Weijia Wang 2019-02-08 13:53:57 +08:00 committed by Weijia Wang
parent 2e405e576b
commit 0b585457ee
3 changed files with 23 additions and 29 deletions

View File

@ -374,10 +374,8 @@ function socketCloseListener() {
// Too bad. That output wasn't getting written. // Too bad. That output wasn't getting written.
// This is pretty terrible that it doesn't raise an error. // This is pretty terrible that it doesn't raise an error.
// Fixed better in v0.10 // Fixed better in v0.10
if (req.output) if (req.outputData)
req.output.length = 0; req.outputData.length = 0;
if (req.outputEncodings)
req.outputEncodings.length = 0;
if (parser) { if (parser) {
parser.finish(); parser.finish();

View File

@ -70,9 +70,7 @@ function OutgoingMessage() {
// Queue that holds all currently pending data, until the response will be // 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). // assigned to the socket (until it will its turn in the HTTP pipeline).
this.output = []; this.outputData = [];
this.outputEncodings = [];
this.outputCallbacks = [];
// `outputSize` is an approximate measure of how much data is queued on this // `outputSize` is an approximate measure of how much data is queued on this
// response. `_onPendingData` will be invoked to update similar global // 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; data = this._header + data;
} else { } else {
var header = this._header; var header = this._header;
if (this.output.length === 0) { if (this.outputData.length === 0) {
this.output = [header]; this.outputData = [{
this.outputEncodings = ['latin1']; data: header,
this.outputCallbacks = [null]; encoding: 'latin1',
callback: null
}];
} else { } else {
this.output.unshift(header); this.outputData.unshift({
this.outputEncodings.unshift('latin1'); data: header,
this.outputCallbacks.unshift(null); encoding: 'latin1',
callback: null
});
} }
this.outputSize += header.length; this.outputSize += header.length;
this._onPendingData(header.length); this._onPendingData(header.length);
@ -254,7 +256,7 @@ function _writeRaw(data, encoding, callback) {
if (conn && conn._httpMessage === this && conn.writable && !conn.destroyed) { if (conn && conn._httpMessage === this && conn.writable && !conn.destroyed) {
// There might be pending data in the this.output buffer. // There might be pending data in the this.output buffer.
if (this.output.length) { if (this.outputData.length) {
this._flushOutput(conn); this._flushOutput(conn);
} else if (!data.length) { } else if (!data.length) {
if (typeof callback === 'function') { if (typeof callback === 'function') {
@ -273,9 +275,7 @@ function _writeRaw(data, encoding, callback) {
return conn.write(data, encoding, callback); return conn.write(data, encoding, callback);
} }
// Buffer, as long as we're not destroyed. // Buffer, as long as we're not destroyed.
this.output.push(data); this.outputData.push({ data, encoding, callback });
this.outputEncodings.push(encoding);
this.outputCallbacks.push(callback);
this.outputSize += data.length; this.outputSize += data.length;
this._onPendingData(data.length); this._onPendingData(data.length);
return false; 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 // There is the first message on the outgoing queue, and we've sent
// everything to the socket. // everything to the socket.
debug('outgoing message end.'); debug('outgoing message end.');
if (this.output.length === 0 && if (this.outputData.length === 0 &&
this.connection && this.connection &&
this.connection._httpMessage === this) { this.connection._httpMessage === this) {
this._finish(); this._finish();
@ -793,22 +793,19 @@ OutgoingMessage.prototype._flush = function _flush() {
OutgoingMessage.prototype._flushOutput = function _flushOutput(socket) { OutgoingMessage.prototype._flushOutput = function _flushOutput(socket) {
var ret; var ret;
var outputLength = this.output.length; var outputLength = this.outputData.length;
if (outputLength <= 0) if (outputLength <= 0)
return ret; return ret;
var output = this.output; var outputData = this.outputData;
var outputEncodings = this.outputEncodings;
var outputCallbacks = this.outputCallbacks;
socket.cork(); socket.cork();
for (var i = 0; i < outputLength; i++) { for (var i = 0; i < outputLength; i++) {
ret = socket.write(output[i], outputEncodings[i], outputCallbacks[i]); const { data, encoding, callback } = outputData[i];
ret = socket.write(data, encoding, callback);
} }
socket.uncork(); socket.uncork();
this.output = []; this.outputData = [];
this.outputEncodings = [];
this.outputCallbacks = [];
this._onPendingData(-this.outputSize); this._onPendingData(-this.outputSize);
this.outputSize = 0; this.outputSize = 0;

View File

@ -69,8 +69,7 @@ server.listen(0, function() {
} }
assert.strictEqual(req.output.length, 0); assert.strictEqual(req.outputData.length, 0);
assert.strictEqual(req.outputEncodings.length, 0);
server.close(); server.close();
})); }));