diff options
author | Luca Casonato <lucacasonato@yahoo.com> | 2021-04-13 02:46:33 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-13 02:46:33 +0200 |
commit | dabce813e064b7b3a2197cb327bde00e7b403688 (patch) | |
tree | af12a13b6fd770de42573bffa4b8261bee246529 /op_crates/fetch/26_fetch.js | |
parent | 9f26e639dd6ddc9416bfd4d12b87efdac2699b1d (diff) |
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.
Diffstat (limited to 'op_crates/fetch/26_fetch.js')
-rw-r--r-- | op_crates/fetch/26_fetch.js | 29 |
1 files changed, 25 insertions, 4 deletions
diff --git a/op_crates/fetch/26_fetch.js b/op_crates/fetch/26_fetch.js index 0bcd8f85c..e713b48ed 100644 --- a/op_crates/fetch/26_fetch.js +++ b/op_crates/fetch/26_fetch.js @@ -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); |