diff options
author | Marcos Casagrande <marcoscvp90@gmail.com> | 2023-08-12 20:29:00 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-08-12 12:29:00 -0600 |
commit | 050ca394096d22330bf5519aad2c59f84be7a0c2 (patch) | |
tree | f03c6374d8ce4f40125c110038566dc079ec55f6 /ext/fetch/23_request.js | |
parent | b34bd640a686d11f8e8e3c3cee8d87980f7809f9 (diff) |
perf(ext/request): optimize validate and normalize HTTP method (#20143)
This PR optimizes `Request` constructor init method step. It doubles the
speed for known lowercased methods. I also added `PATCH` to known
methods
**this patch**
```
benchmark time (avg) iter/s (min … max) p75 p99 p995
---------------------------------------------------------------------------- -----------------------------
method: GET 1.49 µs/iter 669,336.9 (1.35 µs … 2.02 µs) 1.54 µs 2.02 µs 2.02 µs
method: PATCH 1.85 µs/iter 540,921.5 (1.65 µs … 2.02 µs) 1.91 µs 2.02 µs 2.02 µs
method: get 1.49 µs/iter 669,067.9 (1.28 µs … 1.69 µs) 1.55 µs 1.69 µs 1.69 µs
```
**main**
```
cpu: 13th Gen Intel(R) Core(TM) i9-13900H
runtime: deno 1.36.1 (x86_64-unknown-linux-gnu)
benchmark time (avg) iter/s (min … max) p75 p99 p995
---------------------------------------------------------------------------- -----------------------------
method: GET 1.5 µs/iter 665,232.3 (1.3 µs … 2.02 µs) 1.54 µs 2.02 µs 2.02 µs
method: PATCH 2.47 µs/iter 404,052.7 (2.06 µs … 4.05 µs) 2.51 µs 4.05 µs 4.05 µs
method: get 3 µs/iter 333,277.2 (2.72 µs … 4.04 µs) 3.05 µs 4.04 µs 4.04 µs
```
```js
Deno.bench("method: GET", () => {
const r = new Request("https://deno.land", {
method: "GET",
});
});
Deno.bench("method: PATCH", () => {
const r = new Request("https://deno.land", {
method: "PATCH",
body: '{"foo": "bar"}',
});
});
Deno.bench("method: get", () => {
const r = new Request("https://deno.land", {
method: "get",
});
});
```
Diffstat (limited to 'ext/fetch/23_request.js')
-rw-r--r-- | ext/fetch/23_request.js | 45 |
1 files changed, 22 insertions, 23 deletions
diff --git a/ext/fetch/23_request.js b/ext/fetch/23_request.js index cfdce01d3..5232cc13c 100644 --- a/ext/fetch/23_request.js +++ b/ext/fetch/23_request.js @@ -202,31 +202,29 @@ function cloneInnerRequest(request, skipBody = false) { }; } -/** - * @param {string} m - * @returns {boolean} - */ -function isKnownMethod(m) { - return ( - m === "DELETE" || - m === "GET" || - m === "HEAD" || - m === "OPTIONS" || - m === "POST" || - m === "PUT" - ); -} +// method => normalized method +const KNOWN_METHODS = { + "DELETE": "DELETE", + "delete": "DELETE", + "GET": "GET", + "get": "GET", + "HEAD": "HEAD", + "head": "HEAD", + "OPTIONS": "OPTIONS", + "options": "OPTIONS", + "PATCH": "PATCH", + "patch": "PATCH", + "POST": "POST", + "post": "POST", + "PUT": "PUT", + "put": "PUT", +}; + /** * @param {string} m * @returns {string} */ function validateAndNormalizeMethod(m) { - // Fast path for well-known methods - if (isKnownMethod(m)) { - return m; - } - - // Regular path if (RegExpPrototypeExec(HTTP_TOKEN_CODE_POINT_RE, m) === null) { throw new TypeError("Method is not valid."); } @@ -325,9 +323,10 @@ class Request { // 25. if (init.method !== undefined) { - let method = init.method; - method = validateAndNormalizeMethod(method); - request.method = method; + const method = init.method; + // fast path: check for known methods + request.method = KNOWN_METHODS[method] ?? + validateAndNormalizeMethod(method); } // 26. |