1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-11 00:21:05 -05:00

perf(ext/http): optimize set_response for small responses (#20527)

This PR introduces an optimization to `set_response` to reduce the
overhead for responses with a payload size less than 64 bytes.
Performance gains are more noticeable when `is_request_compressible`
enters the slow path, ie: `-H 'Accept-Encoding: unknown'`

### Benchmarks
```js
Deno.serve({ port: 3000 }, () => new Response("hello"));
```
```
wrk -d 10s --latency -H 'Accept-Encoding: slow' http://127.0.0.1:3000
```
---
**main**
```
Running 10s test @ http://127.0.0.1:3000
  2 threads and 10 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    44.72us   28.12us   3.10ms   97.95%
    Req/Sec   112.73k     8.25k  123.66k    91.09%
  2264092 requests in 10.10s, 308.77MB read
Requests/sec: 224187.08
Transfer/sec:     30.57MB
```
**this PR**
```
Running 10s test @ http://127.0.0.1:3000
  2 threads and 10 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    42.91us   20.57us   2.04ms   97.36%
    Req/Sec   116.61k     7.95k  204.81k    88.56%
  2330970 requests in 10.10s, 317.89MB read
Requests/sec: 230806.32
Transfer/sec:     31.48MB
```
This commit is contained in:
Marcos Casagrande 2023-09-16 23:15:15 +02:00 committed by GitHub
parent d13e6e6db8
commit 16b7c9cd8d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -463,7 +463,18 @@ pub fn op_http_set_response_trailers(
*http.trailers().borrow_mut() = Some(trailer_map);
}
fn is_request_compressible(headers: &HeaderMap) -> Compression {
fn is_request_compressible(
length: Option<usize>,
headers: &HeaderMap,
) -> Compression {
if let Some(length) = length {
// By the time we add compression headers and Accept-Encoding, it probably doesn't make sense
// to compress stuff that's smaller than this.
if length < 64 {
return Compression::None;
}
}
let Some(accept_encoding) = headers.get(ACCEPT_ENCODING) else {
return Compression::None;
};
@ -521,17 +532,9 @@ fn is_response_compressible(headers: &HeaderMap) -> bool {
fn modify_compressibility_from_response(
compression: Compression,
length: Option<usize>,
headers: &mut HeaderMap,
) -> Compression {
ensure_vary_accept_encoding(headers);
if let Some(length) = length {
// By the time we add compression headers and Accept-Encoding, it probably doesn't make sense
// to compress stuff that's smaller than this.
if length < 64 {
return Compression::None;
}
}
if compression == Compression::None {
return Compression::None;
}
@ -592,13 +595,11 @@ fn set_response(
// do all of this work to send the response.
if !http.cancelled() {
let resource = http.take_resource();
let compression = is_request_compressible(&http.request_parts().headers);
let compression =
is_request_compressible(length, &http.request_parts().headers);
let response = http.response();
let compression = modify_compressibility_from_response(
compression,
length,
response.headers_mut(),
);
let compression =
modify_compressibility_from_response(compression, response.headers_mut());
response
.body_mut()
.initialize(response_fn(compression), resource);