mirror of
https://github.com/denoland/deno.git
synced 2025-03-03 09:31:22 -05:00
perf: lazy header instantiation for HTTP requests (#10150)
This commit introduces a performance optimization for the native HTTP server. From my testing it is about 2-6% faster than `main`. Request headers in the HTTP servers are now lazilly instatated when they are accessed, rather than being preemptively wrapped in the `Headers` class.
This commit is contained in:
parent
9f26e639dd
commit
dabce813e0
2 changed files with 28 additions and 6 deletions
|
@ -686,6 +686,7 @@
|
|||
// fastBody and dontValidateUrl allow users to opt out of certain behaviors
|
||||
const fastBody = Symbol("Body#fast");
|
||||
const dontValidateUrl = Symbol("dontValidateUrl");
|
||||
const lazyHeaders = Symbol("lazyHeaders");
|
||||
|
||||
class Body {
|
||||
#contentType = "";
|
||||
|
@ -960,7 +961,7 @@
|
|||
#method = "GET";
|
||||
/** @type {string} */
|
||||
#url = "";
|
||||
/** @type {Headers} */
|
||||
/** @type {Headers | string[][]} */
|
||||
#headers;
|
||||
/** @type {"include" | "omit" | "same-origin" | undefined} */
|
||||
#credentials = "omit";
|
||||
|
@ -999,16 +1000,32 @@
|
|||
}
|
||||
|
||||
let headers;
|
||||
let contentType = "";
|
||||
// prefer headers from init
|
||||
if (init.headers) {
|
||||
headers = new Headers(init.headers);
|
||||
if (init[lazyHeaders] && Array.isArray(init.headers)) {
|
||||
// Trust the headers are valid, and only put them into the `Headers`
|
||||
// strucutre when the user accesses the property. We also assume that
|
||||
// all passed headers are lower-case (as is the case when they come
|
||||
// from hyper in Rust), and that headers are of type
|
||||
// `[string, string][]`.
|
||||
headers = init.headers;
|
||||
for (const tuple of headers) {
|
||||
if (tuple[0] === "content-type") {
|
||||
contentType = tuple[1];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
headers = new Headers(init.headers);
|
||||
contentType = headers.get("content-type") || "";
|
||||
}
|
||||
} else if (input instanceof Request) {
|
||||
headers = input.headers;
|
||||
contentType = headers.get("content-type") || "";
|
||||
} else {
|
||||
headers = new Headers();
|
||||
}
|
||||
|
||||
const contentType = headers.get("content-type") || "";
|
||||
super(b, { contentType });
|
||||
this.#headers = headers;
|
||||
|
||||
|
@ -1016,9 +1033,9 @@
|
|||
if (input.bodyUsed) {
|
||||
throw TypeError(BodyUsedError);
|
||||
}
|
||||
// headers are already set above. no reason to do it again
|
||||
this.#method = input.method;
|
||||
this.#url = input.url;
|
||||
this.#headers = new Headers(input.headers);
|
||||
this.#credentials = input.credentials;
|
||||
} else {
|
||||
// Constructing a URL just for validation is known to be expensive.
|
||||
|
@ -1085,6 +1102,9 @@
|
|||
}
|
||||
|
||||
get headers() {
|
||||
if (!(this.#headers instanceof Headers)) {
|
||||
this.#headers = new Headers(this.#headers);
|
||||
}
|
||||
return this.#headers;
|
||||
}
|
||||
|
||||
|
@ -1515,5 +1535,6 @@
|
|||
createHttpClient,
|
||||
fastBody,
|
||||
dontValidateUrl,
|
||||
lazyHeaders,
|
||||
};
|
||||
})(this);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"use strict";
|
||||
|
||||
((window) => {
|
||||
const { Request, dontValidateUrl, fastBody, Response } =
|
||||
const { Request, dontValidateUrl, lazyHeaders, fastBody, Response } =
|
||||
window.__bootstrap.fetch;
|
||||
const { Headers } = window.__bootstrap.headers;
|
||||
const errors = window.__bootstrap.errors.errors;
|
||||
|
@ -61,8 +61,9 @@
|
|||
const request = new Request(url, {
|
||||
body,
|
||||
method,
|
||||
headers: new Headers(headersList),
|
||||
headers: headersList,
|
||||
[dontValidateUrl]: true,
|
||||
[lazyHeaders]: true,
|
||||
});
|
||||
|
||||
const respondWith = createRespondWith(responseSenderRid, this.#rid);
|
||||
|
|
Loading…
Add table
Reference in a new issue