Skip to content

Commit b96cbbb

Browse files
authored
Merge pull request #333 from cesco69/backpressure-v20-64-0
perf: handling backpressure without timer
2 parents 75ae1ff + 45576f6 commit b96cbbb

3 files changed

Lines changed: 19 additions & 41 deletions

File tree

package-lock.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464
"statuses": "^2.0.2",
6565
"tseep": "^1.3.1",
6666
"type-is": "^2.0.1",
67-
"uWebSockets.js": "github:uNetworking/uWebSockets.js#v20.63.0",
67+
"uWebSockets.js": "github:uNetworking/uWebSockets.js#v20.64.0",
6868
"vary": "^1.1.2"
6969
},
7070
"devDependencies": {

src/response.js

Lines changed: 15 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,7 @@ class Socket extends EventEmitter {
7171
module.exports = class Response extends Writable {
7272
#socket = null;
7373
#ended = false;
74-
#pendingChunks = [];
75-
#lastWriteChunkTime = 0;
76-
#writeTimeout = null;
74+
#pendingCallback = null;
7775
req;
7876
constructor(res, req, app) {
7977
super();
@@ -157,36 +155,21 @@ module.exports = class Response extends Writable {
157155
}
158156

159157
if (this.chunkedTransfer) {
160-
this.#pendingChunks.push(chunk);
161-
const size = this.#pendingChunks.reduce((acc, chunk) => acc + chunk.byteLength, 0);
162-
const now = performance.now();
163-
// the first chunk is sent immediately (!this.#lastWriteChunkTime)
164-
// the other chunks are sent when watermark is reached (size >= HIGH_WATERMARK)
165-
// or if elapsed 50ms of last send (now - this.#lastWriteChunkTime > 50)
166-
if (!this.#lastWriteChunkTime || size >= HIGH_WATERMARK || now - this.#lastWriteChunkTime > 50) {
167-
this._res.write(Buffer.concat(this.#pendingChunks, size));
168-
this.#pendingChunks = [];
169-
this.#lastWriteChunkTime = now;
170-
if(this.#writeTimeout) {
171-
clearTimeout(this.#writeTimeout);
172-
this.#writeTimeout = null;
173-
}
174-
} else if(!this.#writeTimeout) {
175-
this.#writeTimeout = setTimeout(() => {
176-
this.#writeTimeout = null;
177-
if(!this.finished && !this.aborted) this._res.cork(() => {
178-
if(this.#pendingChunks.length) {
179-
const size = this.#pendingChunks.reduce((acc, chunk) => acc + chunk.byteLength, 0);
180-
this._res.write(Buffer.concat(this.#pendingChunks, size));
181-
this.#pendingChunks = [];
182-
this.#lastWriteChunkTime = performance.now();
183-
}
184-
});
185-
}, 50);
186-
this.#writeTimeout.unref();
158+
const ok = this._res.write(chunk);
159+
if (ok) {
160+
this.writingChunk = false;
161+
callback(null);
162+
} else {
163+
this.#pendingCallback = callback;
164+
this._res.onWritable(() => {
165+
if (this.aborted || this.finished) return true;
166+
const cb = this.#pendingCallback;
167+
this.#pendingCallback = null;
168+
this.writingChunk = false;
169+
if (cb) cb(null);
170+
return true;
171+
});
187172
}
188-
this.writingChunk = false;
189-
callback(null);
190173
} else {
191174
const lastOffset = this._res.getWriteOffset();
192175
const [ok, done] = this._res.tryEnd(chunk, this.totalSize);
@@ -312,11 +295,6 @@ module.exports = class Response extends Writable {
312295
if(!data && contentLength) {
313296
this._res.endWithoutBody(contentLength.toString());
314297
} else {
315-
if(this.#pendingChunks.length) {
316-
this._res.write(Buffer.concat(this.#pendingChunks));
317-
this.#pendingChunks = [];
318-
this.lastWriteChunkTime = 0;
319-
}
320298
if(data instanceof Buffer) {
321299
data = data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
322300
}

0 commit comments

Comments
 (0)