From 6b1a9761812c2f373e52684ae4be8fb939e589b7 Mon Sep 17 00:00:00 2001 From: Marcos Casagrande Date: Thu, 10 Aug 2023 19:45:55 +0200 Subject: perf(ext/http): use ServeHandlerInfo class instead of object literal (#20122) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR improves performance of `Deno.Serve` when providing `info` argument by creating `ServeHandlerInfo` class instead of creating an object literal with a getter on every request. ```js Deno.serve((_req, info) => new Response(info.remoteAddr.transport) }); ``` ### Benchmarks ``` wrk -d 10s --latency http://127.0.0.1:4500 Running 10s test @ http://127.0.0.1:4500 2 threads and 10 connections Thread Stats Avg Stdev Max +/- Stdev Latency 42.34us 16.30us 1.66ms 95.88% Req/Sec 118.17k 2.95k 127.38k 76.73% Latency Distribution 50% 38.00us 75% 41.00us 90% 56.00us 99% 83.00us 2375298 requests in 10.10s, 319.40MB read Requests/sec: 235177.04 Transfer/sec: 31.62MB ``` **main** ``` wrk -d 10s --latency http://127.0.0.1:4500 Running 10s test @ http://127.0.0.1:4500 2 threads and 10 connections Thread Stats Avg Stdev Max +/- Stdev Latency 78.86us 211.06us 3.58ms 96.52% Req/Sec 105.90k 4.35k 117.41k 78.22% Latency Distribution 50% 41.00us 75% 53.00us 90% 62.00us 99% 1.18ms 2127534 requests in 10.10s, 286.09MB read Requests/sec: 210647.49 Transfer/sec: 28.33MB ``` ``` 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 -------------------------------------------------------------------------- ----------------------------- new ServeHandlerInfo 3.43 ns/iter 291,508,889.3 (3.07 ns … 12.21 ns) 3.42 ns 3.84 ns 3.87 ns {} with getter 133.84 ns/iter 7,471,528.9 (92.9 ns … 458.95 ns) 132.45 ns 364.96 ns 429.43 ns ``` ---- ### Drawbacks: `.remoteAddr` is now not enumerable ``` ServeHandlerInfo {} ``` vs ``` { remoteAddr: [Getter] } ``` It'll break any code trying to iterate through `info` keys (Doubt there's anyone doing it though) ```js Deno.serve((req, info) => { console.log(Object.keys(info).length === 0) // true; return new Response("yes"); }); --- ext/http/00_serve.js | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'ext/http/00_serve.js') diff --git a/ext/http/00_serve.js b/ext/http/00_serve.js index af4353e0e..3447f48e2 100644 --- a/ext/http/00_serve.js +++ b/ext/http/00_serve.js @@ -369,6 +369,16 @@ class CallbackContext { } } +class ServeHandlerInfo { + #inner = null; + constructor(inner) { + this.#inner = inner; + } + get remoteAddr() { + return this.#inner.remoteAddr; + } +} + function fastSyncResponseOrStream(req, respBody) { if (respBody === null || respBody === undefined) { // Don't set the body @@ -535,11 +545,10 @@ function mapToCallback(context, callback, onError) { if (hasOneCallback) { response = await callback(request); } else { - response = await callback(request, { - get remoteAddr() { - return innerRequest.remoteAddr; - }, - }); + response = await callback( + request, + new ServeHandlerInfo(innerRequest), + ); } } else { response = await callback(); -- cgit v1.2.3