1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-28 16:20:57 -05:00

perf(ext/headers): use regex.test instead of .exec (#20125)

This PR improves the performance of `Headers.get` by using `Regex.test`
instead of `.exec`. Also replaced the `Map` used for caching with an
object which is a bit faster

**This patch**

```
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
----------------------------------------------------------------------- -----------------------------
Headers.get           124.71 ns/iter   8,018,687.3 (115.11 ns … 265.66 ns) 126.05 ns 136.12 ns 142.37 ns
```

**1.36.1**

```
cpu: 13th Gen Intel(R) Core(TM) i9-13900H
runtime: deno 1.36.0 (x86_64-unknown-linux-gnu)

benchmark              time (avg)        iter/s             (min … max)       p75       p99      p995
----------------------------------------------------------------------- -----------------------------
Headers.get           218.91 ns/iter   4,568,172.3 (165.37 ns … 264.44 ns) 241.62 ns 260.94 ns 262.67 ns
```

```js
const headers = new Headers({
  "Content-Type": "application/json",
  "Date": "Thu, 10 Aug 2023 07:45:10 GMT",
  "X-Deno": "Deno",
  "Powered-By": "Deno",
  "Content-Encoding": "gzip",
  "Set-Cookie": "__Secure-ID=123; Secure; Domain=example.com",
  "Content-Length": "150",
  "Vary": "Accept-Encoding, Accept, X-Requested-With",
});

Deno.bench("Headers.get", () => {
  headers.get("x-deno");
});
```
This commit is contained in:
Marcos Casagrande 2023-08-12 18:42:23 +02:00 committed by Divy Srivastava
parent 7bca4d3455
commit e152f4002e

View file

@ -28,12 +28,7 @@ const {
ArrayPrototypeSplice,
ObjectEntries,
ObjectHasOwn,
RegExpPrototypeExec,
SafeMap,
MapPrototypeGet,
MapPrototypeHas,
MapPrototypeSet,
MapPrototypeClear,
RegExpPrototypeTest,
Symbol,
SymbolFor,
SymbolIterator,
@ -102,19 +97,23 @@ function checkForInvalidValueChars(value) {
return true;
}
const HEADER_NAME_CACHE = new SafeMap();
let HEADER_NAME_CACHE = {};
let HEADER_CACHE_SIZE = 0;
const HEADER_NAME_CACHE_SIZE_BOUNDARY = 4096;
function checkHeaderNameForHttpTokenCodePoint(name) {
if (MapPrototypeHas(HEADER_NAME_CACHE, name)) {
return MapPrototypeGet(HEADER_NAME_CACHE, name);
const fromCache = HEADER_NAME_CACHE[name];
if (fromCache !== undefined) {
return fromCache;
}
const valid = RegExpPrototypeExec(HTTP_TOKEN_CODE_POINT_RE, name) !== null;
const valid = RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, name);
if (HEADER_NAME_CACHE.size > HEADER_NAME_CACHE_SIZE_BOUNDARY) {
MapPrototypeClear(HEADER_NAME_CACHE);
if (HEADER_CACHE_SIZE > HEADER_NAME_CACHE_SIZE_BOUNDARY) {
HEADER_NAME_CACHE = {};
HEADER_CACHE_SIZE = 0;
}
MapPrototypeSet(HEADER_NAME_CACHE, name, valid);
HEADER_CACHE_SIZE++;
HEADER_NAME_CACHE[name] = valid;
return valid;
}