| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 6409983 commit c2c31d6
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,35 @@ | |||
| 1 | + // Responses sent as a single res.end(string) with a known Content-Length - | ||
| 2 | + // the shape a JSON or HTML endpoint produces. | ||
| 3 | + 'use strict'; | ||
| 4 | + | ||
| 5 | + const common = require('../common.js'); | ||
| 6 | + | ||
| 7 | + const bench = common.createBenchmark(main, { | ||
| 8 | + len: [4, 64, 1024, 16384, 102400], | ||
| 9 | + c: [50], | ||
| 10 | + duration: 5, | ||
| 11 | + }); | ||
| 12 | + | ||
| 13 | + function main({ len, c, duration }) { | ||
| 14 | + const http = require('http'); | ||
| 15 | + const body = 'a'.repeat(len); | ||
| 16 | + const headers = { | ||
| 17 | + 'Content-Type': 'text/plain', | ||
| 18 | + 'Content-Length': `${len}`, | ||
| 19 | + }; | ||
| 20 | + | ||
| 21 | + const server = http.createServer((req, res) => { | ||
| 22 | + res.writeHead(200, headers); | ||
| 23 | + res.end(body); | ||
| 24 | + }); | ||
| 25 | + | ||
| 26 | + server.listen(0, () => { | ||
| 27 | + bench.http({ | ||
| 28 | + connections: c, | ||
| 29 | + duration, | ||
| 30 | + port: server.address().port, | ||
| 31 | + }, () => { | ||
| 32 | + server.close(); | ||
| 33 | + }); | ||
| 34 | + }); | ||
| 35 | + } | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1026,6 +1026,25 @@ function write_(msg, chunk, encoding, callback, fromEnd) { | |||
| 1026 | 1026 | } | |
| 1027 | 1027 | ||
| 1028 | 1028 | ||
| 1029 | + // If this last write can be delivered immediately as the final chunk, this | ||
| 1030 | + // prepares to do so, and then returns true. If not, it returns false and | ||
| 1031 | + // a separate _send call and tick will be required to finish up. | ||
| 1032 | + function maybePrepareFinalChunk(msg, chunk, encoding) { | ||
| 1033 | + if (typeof chunk !== 'string' && !isUint8Array(chunk)) | ||
| 1034 | + return false; | ||
| 1035 | + | ||
| 1036 | + if (msg.destroyed || msg.strictContentLength) | ||
| 1037 | + return false; | ||
| 1038 | + | ||
| 1039 | + if (!msg._header) { | ||
| 1040 | + msg._contentLength = typeof chunk === 'string' ? | ||
| 1041 | + Buffer.byteLength(chunk, encoding) : chunk.byteLength; | ||
| 1042 | + msg._implicitHeader(); | ||
| 1043 | + } | ||
| 1044 | + | ||
| 1045 | + return !!msg._header && msg._hasBody && !msg.chunkedEncoding; | ||
| 1046 | + } | ||
| 1047 | + | ||
| 1029 | 1048 | function connectionCorkNT(conn) { | |
| 1030 | 1049 | conn.uncork(); | |
| 1031 | 1050 | } | |
@@ -1131,6 +1150,8 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) { | |||
| 1131 | 1150 | encoding = null; | |
| 1132 | 1151 | } | |
| 1133 | 1152 | ||
| 1153 | + let finishCallback = null; | ||
| 1154 | + | ||
| 1134 | 1155 | if (chunk) { | |
| 1135 | 1156 | if (this.finished) { | |
| 1136 | 1157 | onError(this, | |
@@ -1143,7 +1164,18 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) { | |||
| 1143 | 1164 | this[kSocket].cork(); | |
| 1144 | 1165 | } | |
| 1145 | 1166 | ||
| 1146 | - write_(this, chunk, encoding, null, true); | ||
| 1167 | + if (maybePrepareFinalChunk(this, chunk, encoding)) { | ||
| 1168 | + // If just one final write is required, with nothing to follow, we | ||
| 1169 | + // attach finish to the write to avoid a separate send() & tick step | ||
| 1170 | + // later on - this is purely a performance optimization. | ||
| 1171 | + if (typeof callback === 'function') { | ||
| 1172 | + queueEndCallback(this, callback); | ||
| 1173 | + callback = undefined; | ||
| 1174 | + } | ||
| 1175 | + finishCallback = onFinish.bind(undefined, this); | ||
| 1176 | + } | ||
| 1177 | + | ||
| 1178 | + write_(this, chunk, encoding, finishCallback, true); | ||
| 1147 | 1179 | } else if (this.finished) { | |
| 1148 | 1180 | if (typeof callback === 'function') { | |
| 1149 | 1181 | queueEndCallback(this, callback); | |
@@ -1165,14 +1197,17 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) { | |||
| 1165 | 1197 | throw new ERR_HTTP_CONTENT_LENGTH_MISMATCH(this[kBytesWritten], this._contentLength); | |
| 1166 | 1198 | } | |
| 1167 | 1199 | ||
| 1168 | - const finish = onFinish.bind(undefined, this); | ||
| 1200 | + if (finishCallback === null) { | ||
| 1201 | + // If we didn't early finish, send the last data and schedule 'finish' now: | ||
| 1202 | + finishCallback = onFinish.bind(undefined, this); | ||
| 1169 | 1203 | ||
| 1170 | - if (this._hasBody && this.chunkedEncoding) { | ||
| 1171 | - this._send('0\r\n' + this._trailer + '\r\n', 'latin1', finish); | ||
| 1172 | - } else if (!this._headerSent || this.writableLength || chunk) { | ||
| 1173 | - this._send('', 'latin1', finish); | ||
| 1174 | - } else { | ||
| 1175 | - process.nextTick(finish); | ||
| 1204 | + if (this._hasBody && this.chunkedEncoding) { | ||
| 1205 | + this._send('0\r\n' + this._trailer + '\r\n', 'latin1', finishCallback); | ||
| 1206 | + } else if (!this._headerSent || this.writableLength || chunk) { | ||
| 1207 | + this._send('', 'latin1', finishCallback); | ||
| 1208 | + } else { | ||
| 1209 | + process.nextTick(finishCallback); | ||
| 1210 | + } | ||
| 1176 | 1211 | } | |
| 1177 | 1212 | ||
| 1178 | 1213 | if (this[kSocket]) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -15,18 +15,11 @@ const res = new ServerResponse({ | |||
| 15 | 15 | httpVersionMinor: 1 | |
| 16 | 16 | }); | |
| 17 | 17 | ||
| 18 | - let firstChunk = true; | ||
| 19 | - | ||
| 20 | 18 | const ws = new Writable({ | |
| 21 | 19 | write: common.mustCall((chunk, encoding, callback) => { | |
| 22 | - if (firstChunk) { | ||
| 23 | - assert(chunk.toString().endsWith('hello world')); | ||
| 24 | - firstChunk = false; | ||
| 25 | - } else { | ||
| 26 | - assert.strictEqual(chunk.length, 0); | ||
| 27 | - } | ||
| 20 | + assert(chunk.toString().endsWith('hello world')); | ||
| 28 | 21 | setImmediate(callback); | |
| 29 | - }, 2) | ||
| 22 | + }, 1) | ||
| 30 | 23 | }); | |
| 31 | 24 | ||
| 32 | 25 | res.assignSocket(ws); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments