Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(ext/http): Use HttpRecord as response body to track until body completion #20822

Merged
merged 8 commits into from
Nov 13, 2023

Conversation

lrowe
Copy link
Contributor

@lrowe lrowe commented Oct 7, 2023

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 #20809 and #20770.

@lrowe
Copy link
Contributor Author

lrowe commented Oct 7, 2023

It's worth taking a close look at 6548cc8. I'm not sure if we should delay HttpRecord::recycle until after the InnerRequest.close() in the op_http_track promise handler.

Potentially there could be a data race which could lead to a use after free between the recycle and the op_http_track promise handler running. However I'm not sure this is actually possible given it is single threaded.

To avoid this possibility we would add an op call in the promise handler where Rust would explicitly take ownership of the external and delay the HttpRecord::recycle until then.

EDIT: Updated with this approach which avoids the possibility of data race / use after free.

@lrowe lrowe force-pushed the lrowe-http-record-response branch from 6548cc8 to 5ff4e6e Compare October 8, 2023 08:29
@lrowe
Copy link
Contributor Author

lrowe commented Oct 8, 2023

Worth checking if op_http_track is used or planned to be used for anything outside of this repo. I didn't want to remove it but it would simplify things a little bit if it's no longer needed.

@lrowe lrowe force-pushed the lrowe-http-record-response branch from 5ff4e6e to a1ced4b Compare October 8, 2023 20:46
@bartlomieju
Copy link
Member

Worth checking if op_http_track is used or planned to be used for anything outside of this repo. I didn't want to remove it but it would simplify things a little bit if it's no longer needed.

It's not, feel free to remove it if it that makes things easier.

@lrowe lrowe force-pushed the lrowe-http-record-response branch 3 times, most recently from cec80c8 to 3d0271a Compare October 9, 2023 05:37
@lrowe
Copy link
Contributor Author

lrowe commented Oct 9, 2023

I think this is ready for review.

I removed op_http_track but the idea behind it lives on in op_http_set_response_body_resource which is now async, resolving when the body has finished streaming or been cancelled. This is used to prevent the data race by having JS follow up with a call to op_http_close_after_finish. The non-graceful shutdown path now calls tokio::task::yield_now().await to provide the extra tick in which op_http_close_after_finish is called. (I initially tried adding an await new Promise(r => setTimeout(r)) in JS but that caused problems with the leaking timers in the node shim tests.)

@mmastrac
Copy link
Contributor

/bench http[minimal,realistic]

@denobot
Copy link
Collaborator

denobot commented Oct 26, 2023

http[minimal]

rps latency bytes relative
node 83,446 118.55 µs σ=34.59 709,941 kB -72.5%
bun 303,721 32.82 µs σ=18.19 1,494,140 kB best
deno 169,975 57.22 µs σ=15.87 1,396,484 kB -44.0%
deno-baseline 165,819 58.42 µs σ=16.02 1,357,421 kB -45.4%

http[realistic]

rps latency bytes relative
node 83,197 119.48 µs σ=37.56 898,437 kB -58.0%
bun 197,924 57.95 µs σ=128.12 1,845,703 kB best
deno 144,103 67.63 µs σ=21.62 1,523,437 kB -27.2%
deno-baseline 138,910 70.36 µs σ=21.24 1,474,609 kB -29.8%

start: Thu, 26 Oct 2023 21:54:51 GMT

id: b4e2c02b-e9c0-4f71-9965-e12b456d7231

server: 0db37f71-5217-4077-8a2f-ff13c98f1b66

@mmastrac mmastrac self-assigned this Nov 3, 2023
@mmastrac mmastrac self-requested a review November 3, 2023 14:21
@mmastrac
Copy link
Contributor

mmastrac commented Nov 3, 2023

Blocked on denoland/deno_core#301 which will give us safer externals

@mmastrac
Copy link
Contributor

/bench http[minimal,realistic]

@denobot
Copy link
Collaborator

denobot commented Nov 13, 2023

http[minimal]

rps latency bytes relative
node 88,040 112.4 µs σ=35.91 749,033 kB -71.8%
bun 312,050 31.96 µs σ=18.09 1,533,203 kB best
deno 173,039 56.05 µs σ=16.3 1,416,015 kB -44.5%
deno-baseline 166,108 58.33 µs σ=17.2 1,357,421 kB -46.8%

http[realistic]

rps latency bytes relative
node 88,288 111.98 µs σ=35.92 947,265 kB -54.9%
bun 195,831 58.17 µs σ=125.8 1,826,171 kB best
deno 141,422 69.23 µs σ=22.67 1,503,906 kB -27.8%
deno-baseline 138,761 70.56 µs σ=22.8 1,474,609 kB -29.1%

start: Mon, 13 Nov 2023 15:57:06 GMT

id: 9cdf6828-83d3-48ff-837f-35ed3fc61088

server: dac869c6-d89b-4eca-9265-951d45881f44

Copy link
Contributor

@mmastrac mmastrac left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Great perf win.

@mmastrac mmastrac enabled auto-merge (squash) November 13, 2023 18:52
@mmastrac mmastrac merged commit e581977 into denoland:main Nov 13, 2023
13 checks passed
kt3k pushed a commit that referenced this pull request Nov 17, 2023
…dy 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 #20809 and
#20770.

---------

Co-authored-by: Matt Mastracci <[email protected]>
zifeo pushed a commit to metatypedev/deno that referenced this pull request Nov 22, 2023
…dy completion (denoland#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 denoland#20809 and
denoland#20770.

---------

Co-authored-by: Matt Mastracci <[email protected]>
mmastrac added a commit that referenced this pull request Nov 23, 2023
Follow-up to #20822. cc @lrowe 

The `httpServerExplicitResourceManagement` tests were randomly failing
on CI because of a race.

The `drain` waker was missing wakeup events if the listeners shut down
after the last HTTP response finished. If we lost the race (rare), the
server Rc would be dropped and we wouldn't poll it again.

This replaces the drain waker system with a signalling Rc that always
resolves when the refcount is about to become 1.

Fix verified by running serve tests in a loop:

```
for i in {0..100}; do cargo run --features=__http_tracing -- test
 -A --unstable '/Users/matt/Documents/github/deno/deno/cli/tests/unit/ser
ve_test.ts' --filter httpServerExplicitResourceManagement; done;
```
crowlKats pushed a commit that referenced this pull request Nov 24, 2023
Follow-up to #20822. cc @lrowe

The `httpServerExplicitResourceManagement` tests were randomly failing
on CI because of a race.

The `drain` waker was missing wakeup events if the listeners shut down
after the last HTTP response finished. If we lost the race (rare), the
server Rc would be dropped and we wouldn't poll it again.

This replaces the drain waker system with a signalling Rc that always
resolves when the refcount is about to become 1.

Fix verified by running serve tests in a loop:

```
for i in {0..100}; do cargo run --features=__http_tracing -- test
 -A --unstable '/Users/matt/Documents/github/deno/deno/cli/tests/unit/ser
ve_test.ts' --filter httpServerExplicitResourceManagement; done;
```

(cherry picked from commit 68a0877)
bartlomieju pushed a commit that referenced this pull request Nov 24, 2023
Follow-up to #20822. cc @lrowe 

The `httpServerExplicitResourceManagement` tests were randomly failing
on CI because of a race.

The `drain` waker was missing wakeup events if the listeners shut down
after the last HTTP response finished. If we lost the race (rare), the
server Rc would be dropped and we wouldn't poll it again.

This replaces the drain waker system with a signalling Rc that always
resolves when the refcount is about to become 1.

Fix verified by running serve tests in a loop:

```
for i in {0..100}; do cargo run --features=__http_tracing -- test
 -A --unstable '/Users/matt/Documents/github/deno/deno/cli/tests/unit/ser
ve_test.ts' --filter httpServerExplicitResourceManagement; done;
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants