Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: lazy header instantiation for HTTP requests #10150

Merged
merged 1 commit into from
Apr 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
perf: lazy header instantiation for HTTP requests
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.
  • Loading branch information
lucacasonato committed Apr 12, 2021
commit 4f639d530c6d7e5e39896419c77a1a56b01651cf
29 changes: 25 additions & 4 deletions op_crates/fetch/26_fetch.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = "";
Expand Down Expand Up @@ -946,7 +947,7 @@
#method = "GET";
/** @type {string} */
#url = "";
/** @type {Headers} */
/** @type {Headers | string[][]} */
#headers;
/** @type {"include" | "omit" | "same-origin" | undefined} */
#credentials = "omit";
Expand Down Expand Up @@ -985,26 +986,42 @@
}

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;

if (input instanceof Request) {
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.
Expand Down Expand Up @@ -1071,6 +1088,9 @@
}

get headers() {
if (!(this.#headers instanceof Headers)) {
this.#headers = new Headers(this.#headers);
}
return this.#headers;
}

Expand Down Expand Up @@ -1501,5 +1521,6 @@
createHttpClient,
fastBody,
dontValidateUrl,
lazyHeaders,
};
})(this);
5 changes: 3 additions & 2 deletions runtime/js/40_http.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down