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

perf(ext/streams): fast path when consuming body of tee'd stream #16329

Merged
merged 2 commits into from
Oct 24, 2022

Conversation

marcosc90
Copy link
Contributor

Add a fast path for consuming the body of cloned Request/Response, which is very common specially when using cache API.

patch - deno_post_bin

Running 20s test @ http://127.0.0.1:4558/
  138683 requests in 20.10s, 19.05MB read
Requests/sec:   6899.70
Transfer/sec:      0.95MB

patch - deno_post_json

Running 20s test @ http://127.0.0.1:4558/
  312885 requests in 20.10s, 42.37MB read
Requests/sec:  15566.42
Transfer/sec:      2.11MB

main - deno_post_bin

Running 20s test @ http://127.0.0.1:4558/
  2 threads and 10 connections
  107811 requests in 20.00s, 14.81MB read
Requests/sec:   5389.68
Transfer/sec:    757.92KB

main - deno_post_json

Running 20s test @ http://127.0.0.1:4558/
  2 threads and 10 connections
  246295 requests in 20.00s, 33.35MB read
Requests/sec:  12313.82
Transfer/sec:      1.67MB

Modified the following for benching

const json = await request.json();

        // const json = await request.json();
        const clone = request.clone();
        const [json] = await Promise.all([
          request.json(),
          clone.json(),
        ]);

@bartlomieju bartlomieju added this to the 1.27 milestone Oct 22, 2022
Copy link
Member

@lucacasonato lucacasonato left a comment

Choose a reason for hiding this comment

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

I don't think this works. If the A side reads the stream, the B side gets nothing because the underlying resource has been read now.

@marcosc90
Copy link
Contributor Author

I don't think this works. If the A side reads the stream, the B side gets nothing because the underlying resource has been read now.

To avoid that, I placed the fast path inside ReadableByteStreamController.pull, so controller.enqueue can be used so the read chunks are enqueued correctly to the other branch.

deno/ext/web/06_streams.js

Lines 684 to 696 in d65f4b3

async pull(controller) {
const v = controller.byobRequest.view;
try {
if (controller[_readAll] === true) {
// fast path for tee'd streams consuming body
const chunk = await core.readAll(rid);
if (chunk.byteLength > 0) {
controller.enqueue(chunk);
}
controller.close();
tryClose();
return;
}

All the tests I've done work as expected so does all WPT.

Copy link
Member

@lucacasonato lucacasonato left a comment

Choose a reason for hiding this comment

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

Sorry, I misunderstood what this does. LGTM, thanks.

@lucacasonato lucacasonato merged commit b7d86b4 into denoland:main Oct 24, 2022
@marcosc90 marcosc90 deleted the perf-response-clone-consume branch October 24, 2022 14:17
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.

3 participants