mirror of
https://github.com/denoland/deno.git
synced 2025-08-04 02:48:24 +00:00
perf(ext/fetch): use content-length in InnerBody.consume (#15925)
This fast path prevents repeated allocations when receiving a fetch body with a known size. Co-authored-by: Luca Casonato <hello@lcas.dev>
This commit is contained in:
parent
1628dba6db
commit
c7dd842f84
4 changed files with 164 additions and 4 deletions
|
@ -64,10 +64,12 @@
|
|||
}
|
||||
|
||||
class InnerBody {
|
||||
#knownExactLength = null;
|
||||
|
||||
/**
|
||||
* @param {ReadableStream<Uint8Array> | { body: Uint8Array | string, consumed: boolean }} stream
|
||||
*/
|
||||
constructor(stream) {
|
||||
constructor(stream, knownExactLength) {
|
||||
/** @type {ReadableStream<Uint8Array> | { body: Uint8Array | string, consumed: boolean }} */
|
||||
this.streamOrStatic = stream ??
|
||||
{ body: new Uint8Array(), consumed: false };
|
||||
|
@ -75,6 +77,8 @@
|
|||
this.source = null;
|
||||
/** @type {null | number} */
|
||||
this.length = null;
|
||||
|
||||
this.#knownExactLength = knownExactLength;
|
||||
}
|
||||
|
||||
get stream() {
|
||||
|
@ -147,14 +151,31 @@
|
|||
const reader = this.stream.getReader();
|
||||
/** @type {Uint8Array[]} */
|
||||
const chunks = [];
|
||||
|
||||
let finalBuffer = this.#knownExactLength
|
||||
? new Uint8Array(this.#knownExactLength)
|
||||
: null;
|
||||
|
||||
let totalLength = 0;
|
||||
while (true) {
|
||||
const { value: chunk, done } = await reader.read();
|
||||
if (done) break;
|
||||
ArrayPrototypePush(chunks, chunk);
|
||||
|
||||
if (finalBuffer) {
|
||||
// fast path, content-length is present
|
||||
TypedArrayPrototypeSet(finalBuffer, chunk, totalLength);
|
||||
} else {
|
||||
// slow path, content-length is not present
|
||||
ArrayPrototypePush(chunks, chunk);
|
||||
}
|
||||
totalLength += chunk.byteLength;
|
||||
}
|
||||
const finalBuffer = new Uint8Array(totalLength);
|
||||
|
||||
if (finalBuffer) {
|
||||
return finalBuffer;
|
||||
}
|
||||
|
||||
finalBuffer = new Uint8Array(totalLength);
|
||||
let i = 0;
|
||||
for (const chunk of chunks) {
|
||||
TypedArrayPrototypeSet(finalBuffer, chunk, i);
|
||||
|
@ -199,7 +220,7 @@
|
|||
clone() {
|
||||
const [out1, out2] = this.stream.tee();
|
||||
this.streamOrStatic = out1;
|
||||
const second = new InnerBody(out2);
|
||||
const second = new InnerBody(out2, this.#knownExactLength);
|
||||
second.source = core.deserialize(core.serialize(this.source));
|
||||
second.length = this.length;
|
||||
return second;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue