1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-26 16:09:27 -05:00
Commit graph

36 commits

Author SHA1 Message Date
Marcos Casagrande
ddbb5fdfb0
perf(ext/node): optimize http headers (#20163)
This PR optimizes Node's `IncomingMessageForServer.headers` by replacing
`Object.fromEntries()` with a loop and `headers.entries` with
`headersEntries` which returns the internal array directly instead of an
iterator

## Benchmarks

Using `wrk` with 5 headers

```
wrk -d 10s --latency -H "X-Deno: true" -H "Accept: application/json" -H "X-Foo: bar" -H "User-Agent: wrk" -H "Accept-Encoding: gzip, br" http://127.0.0.1:3000
```

**this PR**

```
Running 10s test @ http://127.0.0.1:3000
  2 threads and 10 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   167.53us  136.89us   2.75ms   97.33%
    Req/Sec    31.98k     1.38k   36.39k    70.30%
  Latency Distribution
     50%  134.00us
     75%  191.00us
     90%  234.00us
     99%  544.00us
  642548 requests in 10.10s, 45.96MB read
Requests/sec:  63620.36
Transfer/sec:      4.55MB
```

**main**

```
Running 10s test @ http://127.0.0.1:3000
  2 threads and 10 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   181.31us  132.54us   3.79ms   97.13%
    Req/Sec    29.21k     1.45k   32.93k    79.21%
  Latency Distribution
     50%  148.00us
     75%  198.00us
     90%  261.00us
     99%  545.00us
  586939 requests in 10.10s, 41.98MB read
Requests/sec:  58114.01
Transfer/sec:      4.16MB
```

```js
import express from "npm:express";

const app = express();
app.get("/", function (req, res) {
  req.headers;
  res.end();
});
app.listen(3000);
```
2023-08-15 16:59:35 +02:00
Marcos Casagrande
625bd39050
perf(ext/headers): optimize headers iterable (#20155)
This PR makes more optimizations to headers iterable by removing
`ObjectEntries` which was consistently prominent in the flame graph when
benchmarking an express server.

**this PR**

```
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 iter        9.6 µs/iter     104,134.1   (8.74 µs … 131.31 µs)   9.47 µs  12.61 µs  17.81 µ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
------------------------------------------------------------------ -----------------------------
headers iter      12.87 µs/iter      77,675.9  (11.97 µs … 132.34 µs)  12.76 µs  16.49 µs   26.4 µs
```


```js
const headers = new Headers({
  "Content-Type": "application/json",
  "X-Content-Type": "application/json",
  "Date": "Thu, 14 Aug 2023 17: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 iter', () => {
  [...headers]
})
```
2023-08-14 19:13:55 +00:00
Marcos Casagrande
b34bd640a6
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");
});
```
2023-08-12 10:42:23 -06:00
Marcos Casagrande
f843a1fdff
perf(ext/headers): cache iterableHeaders for immutable Headers (#20132)
This PR caches `_iterableHeaders` for immutable `Headers` increasing the
performance of `fetch` & server if headers are iterated.

Should close #19466 

I only cached immutable headers to address this comment
https://github.com/denoland/deno/issues/19466#issuecomment-1589892373
since I didn't find any occurrence of header mutation on immutable
headers. We can discuss caching for non-immutable, but I think this is a
great first step.

## BENCHMARK

### Server
```js
const addr = Deno.args[0] ?? "127.0.0.1:4500";
const [hostname, port] = addr.split(":");
const { serve } = Deno;

serve({ hostname, port: Number(port), reusePort: true }, (req) => {
  const headers = [...req.headers]; // req.headers are immutable, cannot set/append/delete
  return new Response("ok");
});

```
Used `wrk` with 5 headers
```
wrk -d 10s --latency -H "X-Deno: true" -H "Accept: application/json" -H "X-Foo: bar" -H "User-Agent: wrk" -H "Accept-Encoding: gzip, br" http://127.0.0.1:4500
```


**This patch**
```
Running 10s test @ http://127.0.0.1:4500
  2 threads and 10 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    70.18us   22.89us 679.00us   81.37%
    Req/Sec    71.55k     9.69k   82.18k    89.60%
  Latency Distribution
     50%   59.00us
     75%   89.00us
     90%   98.00us
     99%  159.00us
  1437891 requests in 10.10s, 193.35MB read
Requests/sec: 142369.83
Transfer/sec:     19.14MB
```
**main**
```
Running 10s test @ http://127.0.0.1:4500
  2 threads and 10 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   112.78us   36.47us   2.09ms   77.99%
    Req/Sec    44.30k     1.65k   49.14k    74.26%
  Latency Distribution
     50%   99.00us
     75%  136.00us
     90%  162.00us
     99%  213.00us
  890588 requests in 10.10s, 118.91MB read
Requests/sec:  88176.37
Transfer/sec:     11.77MB
```
### fetch

```js
const res = await fetch('http://127.0.0.1:4500');
Deno.bench("Headers iterator", () => {
  const i = [...res.headers]; // res.headers are immutable, cannot set/append/delete
});
```

**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 iterator      329.5 ns/iter   3,034,909.0 (318.55 ns … 364.34 ns)  331.1 ns 355.72 ns 364.34 ns
```
**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
---------------------------------------------------------------------- -----------------------------
Headers iterator       2.59 µs/iter     386,372.1     (2.56 µs … 2.68 µs)   2.59 µs   2.68 µs   2.68 µs
```
2023-08-12 10:42:06 -06:00
Marcos Casagrande
2d3d0a579d
perf(ext/headers): optimize getHeader using for loop (#20115)
This PR optimizes the `getHeader` function by replacing `.filter` and
`.map` with a `for` loop

**this patch**

```
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      132.2 ns/iter   7,564,093.4 (125.81 ns … 147.66 ns) 133.79 ns 144.92 ns 145.36 ns
```

**main**

```
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     191.48 ns/iter   5,222,523.6 (182.75 ns … 212.22 ns)  193.5 ns 205.96 ns 211.51 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", () => {
  const i = headers.get("x-deno");
});
```
2023-08-10 19:41:09 +02:00
Marcos Casagrande
414274b68a
perf(ext/headers): use .push loop instead of spread operator (#20108) 2023-08-09 19:36:47 -04:00
Luca Casonato
d8e8e60f9f
feat(ext/fetch): add Headers#getSetCookie (#13542)
Spec change: https://github.com/whatwg/fetch/pull/1346
Tests: https://github.com/web-platform-tests/wpt/pull/31442 (ran against
this PR and they all pass)

---------

Co-authored-by: Bartek Iwańczuk <biwanczuk@gmail.com>
2023-07-02 13:20:56 +02:00
markthree
43d5644048
refactor(ext/fetch): const for max header cache size (#19496) 2023-06-15 18:27:21 +02:00
Bartek Iwańczuk
7e81d3c876
perf(http): cache verified headers (#19465)
Use `Map` to cache validated HTTP headers. Cache
has a capacity of 4096 elements and it's cleared
once that capacity is reached.

In `preactssr` benchmark it lowers the time spent
when adding headers from 180ms to 2.5ms.
2023-06-13 21:13:34 +02:00
Bartek Iwańczuk
21c2c01ebe
perf: optimize RegExp usage in JS (#19364)
Towards https://github.com/denoland/deno/issues/19330

Shows about 1% improvement in the HTTP benchmark.
2023-06-05 10:52:40 +02:00
Kenta Moriuchi
49eb887cc6
refactor(core): Use ObjectHasOwn instead of ObjectPrototypeHasOwnProperty (#18952)
ES2022 `Object.hasOwn` can be used in snapshot, so I migrate to use it.
2023-05-02 12:15:45 +02:00
Leo Kettmeir
b31cf9fde6
refactor(webidl): move prefix & context out of converters options bag (#18931) 2023-05-01 10:47:13 +00:00
Bartek Iwańczuk
02da57e275
refactor(ext/webidl): remove option bags from "makeException" (#18679)
Creating these options bags is more costly than passing arguments
one-by-one. Especially since `prefix` and `context` are passed to all functions.
2023-04-20 00:58:41 +02:00
Bartek Iwańczuk
a3c5193a2e
refactor(ext/webidl): remove object from 'requiredArguments' (#18674)
This should produce a little less garbage and using an object here
wasn't really required.

---------

Co-authored-by: Aapo Alasuutari <aapo.alasuutari@gmail.com>
Co-authored-by: Leo Kettmeir <crowlkats@toaxl.com>
2023-04-12 19:58:57 +00:00
Bartek Iwańczuk
72fe9bb470
refactor: rename InternalModuleLoader to ExtModuleLoader, use ext: scheme for snapshotted modules (#18041)
This commit renames "deno_core::InternalModuleLoader" to
"ExtModuleLoader" and changes the specifiers used by the 
modules loaded from this loader to "ext:".

"internal:" scheme was really ambiguous and it's more characters than
"ext:", which should result in slightly smaller snapshot size.

Closes https://github.com/denoland/deno/issues/18020
2023-03-08 12:44:54 +01:00
Kenta Moriuchi
55833cf799
fix(core): introduce SafeRegExp to primordials (#17592) 2023-03-01 08:14:16 +09:00
Leo Kettmeir
49af1ab18d
refactor: remove prefix from include_js_files & use extension name (#17683) 2023-02-07 21:09:50 +00:00
Leo Kettmeir
b4aa153097
refactor: Use ES modules for internal runtime code (#17648)
This PR refactors all internal js files (except core) to be written as
ES modules.
`__bootstrap`has been mostly replaced with static imports in form in
`internal:[path to file from repo root]`.
To specify if files are ESM, an `esm` method has been added to
`Extension`, similar to the `js` method.
A new ModuleLoader called `InternalModuleLoader` has been added to
enable the loading of internal specifiers, which is used in all
situations except when a snapshot is only loaded, and not a new one is
created from it.

---------

Co-authored-by: Bartek Iwańczuk <biwanczuk@gmail.com>
2023-02-07 20:22:46 +01:00
Kenta Moriuchi
ff89ff4abb
perf(ext,runtime): remove using SafeArrayIterator from for-of (#17255) 2023-01-06 21:45:23 +09:00
David Sherret
10e4b2e140
chore: update copyright year to 2023 (#17247)
Yearly tradition of creating extra noise in git.
2023-01-02 21:00:42 +00:00
Kenta Moriuchi
948f85216a
chore: Update dlint (#17031)
Introduces `SafeSetIterator` and `SafeMapIterator` to primordials
2022-12-20 03:37:50 +01:00
Marcos Casagrande
0cd05d7377
fix(ext/fetch): fix illegal header regex (#16236)
This PR fixes invalid header parsing which is flaky because `g` flag is
being used in the regex, which keeps track of `lastIndex`

```javascript
try {
  new Headers([["x", "\u0000x"]]);  // error
} catch(e) {}
new Headers([["x", "\u0000x"]]); // no error
```

This issue affects `Response` & `Request` constructors as well
2022-10-10 12:06:50 -04:00
Satya Rohith
b312279e58
feat: implement Web Cache API (#15829) 2022-09-28 17:41:12 +05:30
apeltop
bb3387de17
chore(ext): fix typo in ext/webgpu, ext/fetch (#14106) 2022-03-25 00:36:30 +01:00
Bartek Iwańczuk
bf22f114a6
refactor: update runtime code for primordial check for iterators (#13510) 2022-02-07 13:54:32 +01:00
Bartek Iwańczuk
8176a4d166
refactor: primordials for instanceof (#13527) 2022-02-01 18:06:11 +01:00
Bartek Iwańczuk
f248e6f177
Revert "refactor: update runtime code for primordial checks for "instanceof" (#13497)" (#13511)
This reverts commit 884143218f.
2022-01-27 16:27:22 +01:00
Bartek Iwańczuk
884143218f
refactor: update runtime code for primordial checks for "instanceof" (#13497) 2022-01-27 13:36:36 +01:00
Ryan Dahl
1fb5858009
chore: update copyright to 2022 (#13306)
Co-authored-by: Erfan Safari <erfanshield@outlook.com>
2022-01-07 22:09:52 -05:00
Luca Casonato
2eae1ae665
revert: store header keys lower case internally (#12837)
This reverts commit 49ec3d10ad.
2021-11-23 01:23:11 +01:00
Aaron O'Mullan
f68825eda0
perf(fetch): optimize fillHeaders() key iteration (#12287)
Reduces self-time by ~70x (~70ms => ~1ms on 1M iters)

for...in filtered by hasOwnProperty yields the same set of keys as Object.keys()
2021-10-01 12:17:16 +02:00
Aaron O'Mullan
68e5cdaff0
perf(web): ~400x faster http header trimming (#12277)
Use a regex substring match with a first/last char fastpath instead of 2 regex replaces. Roughly ~400x faster (423ms vs 0.7ms in profiled runs)
2021-09-30 18:39:55 +02:00
Aaron O'Mullan
6c007aa5ab
perf(fetch/headers): optimize appendHeader (#12234)
Use a single regex to check for `\0`, `\n`, `\r` instead of 3 `String.includes(...)` calls
2021-09-26 20:19:02 +02:00
李瑞丰
46245b830a
fix(ext/webidl): correctly apply [SymbolToStringTag] to interfaces (#11851)
Co-authored-by: Luca Casonato <hello@lcas.dev>
Co-authored-by: Yoshiya Hinosawa <stibium121@gmail.com>
2021-09-25 02:07:22 +09:00
Feng Yu
6f63d739ab
fiz(ext/fetch): Headers constructor error message (#11778) 2021-08-21 05:07:30 +02:00
Ryan Dahl
a0285e2eb8
Rename extensions/ directory to ext/ (#11643) 2021-08-11 12:27:05 +02:00
Renamed from extensions/fetch/20_headers.js (Browse further)