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

Improve performance of WebSockets when there is no timeout #8660

Merged
merged 5 commits into from
Aug 8, 2024

Conversation

bdraco
Copy link
Member

@bdraco bdraco commented Aug 8, 2024

What do these changes do?

The common case for WebSockets is to call receive without a timeout, or use the WebSocketResponse as an async iterator. The read was always wrapped with an async timeout even if the timeout was not used which accounted for as much as 50% of the run time each loop. If there is no timeout, avoid wrapping the read call in the context manager which creates a new Timeout() object each time.

Are there changes in behavior for the user?

Performance improvement

related reading https://www.researchgate.net/publication/348993267_An_Analysis_of_the_Performance_of_Websockets_in_Various_Programming_Languages_and_Libraries

Is it a substantial burden for the maintainers to support this?

no

before
timeout

after
after

The common case for WebSockets is to call receive
without a timeout, or use the WebSocketResponse as
an async iterator. The read was always wrapped with
an async timeout even if the timeout was not used
which accounted for as much as 50% of the run time
each loop. If there is no timeout, avoid wrapping
the read call in the context manager which
creates a new Timeout() object each time.
@bdraco bdraco added this to the 3.10.3 milestone Aug 8, 2024
@bdraco bdraco added backport-3.10 Trigger automatic backporting to the 3.10 release branch by Patchback robot backport-3.11 Trigger automatic backporting to the 3.11 release branch by Patchback robot labels Aug 8, 2024
@bdraco
Copy link
Member Author

bdraco commented Aug 8, 2024

This should significantly help aiounifi, aioshelly, and uiprotect which they are have quite a bit of incoming websocket traffic.

@psf-chronographer psf-chronographer bot added the bot:chronographer:provided There is a change note present in this PR label Aug 8, 2024
@bdraco bdraco marked this pull request as ready for review August 8, 2024 21:56
Copy link

codecov bot commented Aug 8, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 97.97%. Comparing base (6c6ecfa) to head (91775cb).

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #8660   +/-   ##
=======================================
  Coverage   97.97%   97.97%           
=======================================
  Files         107      107           
  Lines       33780    33786    +6     
  Branches     3966     3968    +2     
=======================================
+ Hits        33096    33102    +6     
  Misses        507      507           
  Partials      177      177           
Flag Coverage Δ
CI-GHA 97.88% <100.00%> (+<0.01%) ⬆️
OS-Linux 97.54% <100.00%> (+<0.01%) ⬆️
OS-Windows 95.91% <ø> (ø)
OS-macOS 97.20% <100.00%> (+<0.01%) ⬆️
Py-3.10.11 97.34% <87.50%> (-0.01%) ⬇️
Py-3.10.14 97.28% <87.50%> (-0.01%) ⬇️
Py-3.11.9 97.51% <87.50%> (-0.01%) ⬇️
Py-3.12.4 97.62% <87.50%> (-0.01%) ⬇️
Py-3.8.10 95.56% <ø> (ø)
Py-3.8.18 97.07% <100.00%> (+<0.01%) ⬆️
Py-3.9.13 97.22% <100.00%> (+<0.01%) ⬆️
Py-3.9.19 97.16% <100.00%> (+<0.01%) ⬆️
Py-pypy7.3.16 96.75% <100.00%> (+<0.01%) ⬆️
VM-macos 97.20% <100.00%> (+<0.01%) ⬆️
VM-ubuntu 97.54% <100.00%> (+<0.01%) ⬆️
VM-windows 95.91% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@Dreamsorcerer
Copy link
Member

I wonder if there's a way to improve the timeout version too...

@bdraco
Copy link
Member Author

bdraco commented Aug 8, 2024

I wonder if there's a way to improve the timeout version too...

Nothing obvious stands out in https:/python/cpython/blob/2f5c3b09e45798a18d60841d04a165fb062be666/Lib/asyncio/timeouts.py#L85 but I also haven't stared at it long enough.

@bdraco
Copy link
Member Author

bdraco commented Aug 8, 2024

Thanks!

@bdraco bdraco merged commit 14d5295 into master Aug 8, 2024
37 of 38 checks passed
@bdraco bdraco deleted the websocket_timeout branch August 8, 2024 23:42
Copy link
Contributor

patchback bot commented Aug 8, 2024

Backport to 3.10: 💔 cherry-picking failed — conflicts found

❌ Failed to cleanly apply 14d5295 on top of patchback/backports/3.10/14d52957290e88748f37ed396c68a23d13a7ecda/pr-8660

Backporting merged PR #8660 into master

  1. Ensure you have a local repo clone of your fork. Unless you cloned it
    from the upstream, this would be your origin remote.
  2. Make sure you have an upstream repo added as a remote too. In these
    instructions you'll refer to it by the name upstream. If you don't
    have it, here's how you can add it:
    $ git remote add upstream https:/aio-libs/aiohttp.git
  3. Ensure you have the latest copy of upstream and prepare a branch
    that will hold the backported code:
    $ git fetch upstream
    $ git checkout -b patchback/backports/3.10/14d52957290e88748f37ed396c68a23d13a7ecda/pr-8660 upstream/3.10
  4. Now, cherry-pick PR Improve performance of WebSockets when there is no timeout #8660 contents into that branch:
    $ git cherry-pick -x 14d52957290e88748f37ed396c68a23d13a7ecda
    If it'll yell at you with something like fatal: Commit 14d52957290e88748f37ed396c68a23d13a7ecda is a merge but no -m option was given., add -m 1 as follows instead:
    $ git cherry-pick -m1 -x 14d52957290e88748f37ed396c68a23d13a7ecda
  5. At this point, you'll probably encounter some merge conflicts. You must
    resolve them in to preserve the patch from PR Improve performance of WebSockets when there is no timeout #8660 as close to the
    original as possible.
  6. Push this branch to your fork on GitHub:
    $ git push origin patchback/backports/3.10/14d52957290e88748f37ed396c68a23d13a7ecda/pr-8660
  7. Create a PR, ensure that the CI is green. If it's not — update it so that
    the tests and any other checks pass. This is it!
    Now relax and wait for the maintainers to process your pull request
    when they have some cycles to do reviews. Don't worry — they'll tell you if
    any improvements are necessary when the time comes!

🤖 @patchback
I'm built with octomachinery and
my source is open — https:/sanitizers/patchback-github-app.

Copy link
Contributor

patchback bot commented Aug 8, 2024

Backport to 3.11: 💔 cherry-picking failed — conflicts found

❌ Failed to cleanly apply 14d5295 on top of patchback/backports/3.11/14d52957290e88748f37ed396c68a23d13a7ecda/pr-8660

Backporting merged PR #8660 into master

  1. Ensure you have a local repo clone of your fork. Unless you cloned it
    from the upstream, this would be your origin remote.
  2. Make sure you have an upstream repo added as a remote too. In these
    instructions you'll refer to it by the name upstream. If you don't
    have it, here's how you can add it:
    $ git remote add upstream https:/aio-libs/aiohttp.git
  3. Ensure you have the latest copy of upstream and prepare a branch
    that will hold the backported code:
    $ git fetch upstream
    $ git checkout -b patchback/backports/3.11/14d52957290e88748f37ed396c68a23d13a7ecda/pr-8660 upstream/3.11
  4. Now, cherry-pick PR Improve performance of WebSockets when there is no timeout #8660 contents into that branch:
    $ git cherry-pick -x 14d52957290e88748f37ed396c68a23d13a7ecda
    If it'll yell at you with something like fatal: Commit 14d52957290e88748f37ed396c68a23d13a7ecda is a merge but no -m option was given., add -m 1 as follows instead:
    $ git cherry-pick -m1 -x 14d52957290e88748f37ed396c68a23d13a7ecda
  5. At this point, you'll probably encounter some merge conflicts. You must
    resolve them in to preserve the patch from PR Improve performance of WebSockets when there is no timeout #8660 as close to the
    original as possible.
  6. Push this branch to your fork on GitHub:
    $ git push origin patchback/backports/3.11/14d52957290e88748f37ed396c68a23d13a7ecda/pr-8660
  7. Create a PR, ensure that the CI is green. If it's not — update it so that
    the tests and any other checks pass. This is it!
    Now relax and wait for the maintainers to process your pull request
    when they have some cycles to do reviews. Don't worry — they'll tell you if
    any improvements are necessary when the time comes!

🤖 @patchback
I'm built with octomachinery and
my source is open — https:/sanitizers/patchback-github-app.

bdraco added a commit that referenced this pull request Aug 8, 2024
bdraco added a commit that referenced this pull request Aug 8, 2024
bdraco added a commit that referenced this pull request Aug 9, 2024
bdraco added a commit that referenced this pull request Aug 9, 2024
@bdraco
Copy link
Member Author

bdraco commented Aug 10, 2024

I wonder if there's a way to improve the timeout version too...

Found a way to make it faster python/cpython#122882

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport-3.10 Trigger automatic backporting to the 3.10 release branch by Patchback robot backport-3.11 Trigger automatic backporting to the 3.11 release branch by Patchback robot bot:chronographer:provided There is a change note present in this PR
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants