summaryrefslogtreecommitdiff
path: root/ext/http/response_body.rs
AgeCommit message (Collapse)Author
2024-08-02perf(ext/http): Reduce size of `ResponseBytesInner` (#24840)Nathan Whitaker
I noticed [`set_response_body`](https://github.com/nathanwhit/deno/blob/ce42f82b5a985e5f1482dff97a7268019a8e79ea/ext/http/service.rs#L439-L443) was unexpectedly hot in profiles, with most of the time being spent in `memmove`. It turns out that `ResponseBytesInner` was _massive_ (5624 bytes), so every time we moved a `ResponseBytesInner` (for instance in `set_response_body`) we were doing a >5kb memmove, which adds up pretty quickly. This PR boxes the two larger variants (the compression streams), shrinking `ResponseBytesInner` to a reasonable 48 bytes. --- Benchmarked with a simple hello world server: ```ts // hello-server.ts Deno.serve((_req) => { return new Response("Hello world"); }); // run with `deno run -A hello-server.ts` // in separate terminal `wrk -d 10s http://127.0.0.1:8000` ``` Main: ``` Running 10s test @ http://127.0.0.1:8000/ 2 threads and 10 connections Thread Stats Avg Stdev Max +/- Stdev Latency 53.39us 9.53us 0.98ms 92.78% Req/Sec 86.57k 3.56k 91.58k 91.09% 1739319 requests in 10.10s, 248.81MB read Requests/sec: 172220.92 Transfer/sec: 24.64MB ``` This PR: ``` Running 10s test @ http://127.0.0.1:8000/ 2 threads and 10 connections Thread Stats Avg Stdev Max +/- Stdev Latency 45.44us 8.49us 0.91ms 90.04% Req/Sec 100.65k 2.26k 102.65k 96.53% 2022296 requests in 10.10s, 289.29MB read Requests/sec: 200226.20 Transfer/sec: 28.64MB ``` So a nice ~15% bump. (With response body compression, the gain is ~10% for gzip and neutral for brotli)
2024-06-20refactor(ext): remove use of `brotli::ffi` (#24214)ud2
2024-05-28fix(ext/http): flush gzip streaming response (#23991)Bartek Iwańczuk
This commit changes `gzip` compression in `Deno.serve` API to flush data after each write. There's a slight performance regression, but provided test shows a scenario that was not possible before. --------- Co-authored-by: Divy Srivastava <dj.srivastava23@gmail.com>
2024-05-08chore: enable clippy::print_stdout and clippy::print_stderr (#23732)David Sherret
1. Generally we should prefer to use the `log` crate. 2. I very often accidentally commit `eprintln`s. When we should use `println` or `eprintln`, it's not too bad to be a bit more verbose and ignore the lint rule.
2024-04-24feat(ext/http): Implement request.signal for Deno.serve (#23425)Matt Mastracci
When the response has been successfully send, we abort the `Request.signal` property to indicate that all resources associated with this transaction may be torn down.
2024-01-01chore: update copyright to 2024 (#21753)David Sherret
2023-12-27refactor: simplify hyper, http, h2 deps (#21715)Bartek Iwańczuk
Main change is that: - "hyper" has been renamed to "hyper_v014" to signal that it's legacy - "hyper1" has been renamed to "hyper" and should be the default
2023-12-22chore: update ext/http to hyper 1.0.1 and http 1.0 (#21588)Bartek Iwańczuk
Closes https://github.com/denoland/deno/issues/21583.
2023-11-13refactor(ext/http): Use HttpRecord as response body to track until body ↵Laurence Rowe
completion (#20822) Use HttpRecord as response body so requests can be tracked all the way to response body completion. This allows Request properties to be accessed while the response body is streaming. Graceful shutdown now awaits a future instead of async spinning waiting for requests to finish. On the minimal benchmark this refactor improves performance an additional 2% over pooling alone for a net 3% increase over the previous deno main branch. Builds upon https://github.com/denoland/deno/pull/20809 and https://github.com/denoland/deno/pull/20770. --------- Co-authored-by: Matt Mastracci <matthew@mastracci.com>
2023-11-13refactor(ext/http): refer to HttpRecord directly using v8::External (#20770)Laurence Rowe
Makes the JavaScript Request use a v8:External opaque pointer to directly refer to the Rust HttpRecord. The HttpRecord is now reference counted. To avoid leaks the strong count is checked at request completion. Performance seems unchanged on the minimal benchmark. 118614 req/s this branch vs 118564 req/s on main, but variance between runs on my laptop is pretty high. --------- Co-authored-by: Matt Mastracci <matthew@mastracci.com>
2023-09-25fix(ext/http): ensure that resources are closed when request is cancelled ↵Matt Mastracci
(#20641) Builds on top of #20622 to fix #10854
2023-08-26chore: update to Rust 1.72 (#20258)林炳权
<!-- Before submitting a PR, please read https://deno.com/manual/contributing 1. Give the PR a descriptive title. Examples of good title: - fix(std/http): Fix race condition in server - docs(console): Update docstrings - feat(doc): Handle nested reexports Examples of bad title: - fix #7123 - update docs - fix bugs 2. Ensure there is a related issue and it is referenced in the PR text. 3. Ensure there are tests that cover the changes. 4. Ensure `cargo test` passes. 5. Ensure `./tools/format.js` passes without changing files. 6. Ensure `./tools/lint.js` passes. 7. Open as a draft PR if your work is still in progress. The CI won't run all steps, but you can add '[ci]' to a commit message to force it to. 8. If you would like to run the benchmarks on the CI, add the 'ci-bench' label. --> As the title. --------- Co-authored-by: Matt Mastracci <matthew@mastracci.com>
2023-08-21fix(ext/http): ensure request body resource lives as long as response is ↵Matt Mastracci
alive (#20206) Deno.serve's fast streaming implementation was not keeping the request body resource ID alive. We were taking the `Rc<Resource>` from the resource table during the response, so a hairpin duplex response that fed back the request body would work. However, if any JS code attempted to read from the request body (which requires the resource ID to be valid), the response would fail with a difficult-to-diagnose "EOF" error. This was affecting more complex duplex uses of `Deno.fetch` (though as far as I can tell was unreported). Simple test: ```ts const reader = request.body.getReader(); return new Response( new ReadableStream({ async pull(controller) { const { done, value } = await reader.read(); if (done) { controller.close(); } else { controller.enqueue(value); } }, }), ``` And then attempt to use the stream in duplex mode: ```ts async function testDuplex( reader: ReadableStreamDefaultReader<Uint8Array>, writable: WritableStreamDefaultWriter<Uint8Array>, ) { await writable.write(new Uint8Array([1])); const chunk1 = await reader.read(); assert(!chunk1.done); assertEquals(chunk1.value, new Uint8Array([1])); await writable.write(new Uint8Array([2])); const chunk2 = await reader.read(); assert(!chunk2.done); assertEquals(chunk2.value, new Uint8Array([2])); await writable.close(); const chunk3 = await reader.read(); assert(chunk3.done); } ``` In older versions of Deno, this would just lock up. I believe after 23ff0e722e3c4b0827940853c53c5ee2ede5ec9f, it started throwing a more explicit error: ``` httpServerStreamDuplexJavascript => ./cli/tests/unit/serve_test.ts:1339:6 error: TypeError: request or response body error: error reading a body from connection: Connection reset by peer (os error 54) at async Object.pull (ext:deno_web/06_streams.js:810:27) ```
2023-08-17feat(ext/web): resourceForReadableStream (#20180)Matt Mastracci
Extracted from fast streams work. This is a resource wrapper for `ReadableStream`, allowing us to treat all `ReadableStream` instances as resources, and remove special paths in both `fetch` and `serve`. Performance with a ReadableStream response yields ~18% improvement: ``` return new Response(new ReadableStream({ start(controller) { controller.enqueue(new Uint8Array([104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100])); controller.close(); } }) ``` This patch: ``` 12:36 $ third_party/prebuilt/mac/wrk http://localhost:8080 Running 10s test @ http://localhost:8080 2 threads and 10 connections Thread Stats Avg Stdev Max +/- Stdev Latency 99.96us 100.03us 6.65ms 98.84% Req/Sec 47.73k 2.43k 51.02k 89.11% 959308 requests in 10.10s, 117.10MB read Requests/sec: 94978.71 Transfer/sec: 11.59MB ``` main: ``` Running 10s test @ http://localhost:8080 2 threads and 10 connections Thread Stats Avg Stdev Max +/- Stdev Latency 163.03us 685.51us 19.73ms 99.27% Req/Sec 39.50k 3.98k 66.11k 95.52% 789582 requests in 10.10s, 82.83MB read Requests/sec: 78182.65 Transfer/sec: 8.20MB ```
2023-07-07fix(ext/http): Use brotli compression params (#19758)Matt Mastracci
Fixes #19737 by adding brotli compression parameters. Time after: `Accept-Encoding: gzip`: ``` real 0m0.214s user 0m0.005s sys 0m0.013s ``` `Accept-Encoding: br`: Before: ``` real 0m10.303s user 0m0.005s sys 0m0.010s ``` After: ``` real 0m0.127s user 0m0.006s sys 0m0.014s ```
2023-05-28fix(ext/http): fix a possible memleak in Brotli (#19250)Levente Kurusa
We probably need to free the BrotliEncoderState once the stream has finished.
2023-05-24feat(ext/http): Brotli Compression (#19216)Levente Kurusa
Add Brotli streaming compression to HTTP
2023-05-18feat(ext/http): Add support for trailers w/internal API (HTTP/2 only) (#19182)Matt Mastracci
Necessary for #3326. Requested in #10214 as well.
2023-05-16fix(ext/http): Ensure cancelled requests don't crash Deno.serve (#19154)Matt Mastracci
Fixes for various `Attemped to access invalid request` bugs (#19058, #15427, #17213). We did not wait for both a drop event and a completion event before removing items from the slab table. This ensures that we do so. In addition, the slab methods are refactored out into `slab.rs` for maintainability.
2023-05-10feat(ext/http): Automatic compression for Deno.serve (#19031)Matt Mastracci
`Content-Encoding: gzip` support for `Deno.serve`. This doesn't support Brotli (`br`) yet, however it should not be difficult to add. Heuristics for compression are modelled after those in `Deno.serveHttp`. Tests are provided to ensure that the gzip compression is correct. We chunk a number of different streams (zeros, hard-to-compress data, already-gzipped data) in a number of different ways (regular, random, large/small, small/large).
2023-04-22feat(ext/http): Rework Deno.serve using hyper 1.0-rc3 (#18619)Matt Mastracci
This is a rewrite of the `Deno.serve` API to live on top of hyper 1.0-rc3. The code should be more maintainable long-term, and avoids some of the slower mpsc patterns that made the older code less efficient than it could have been. Missing features: - `upgradeHttp` and `upgradeHttpRaw` (`upgradeWebSocket` is available, however). - Automatic compression is unavailable on responses.