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

Change websocket cleanup performance from O(n^2) to O(n). #429

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

marshallbrekka
Copy link

Move subscription tracking to a dict keyed by the underlying websocket object.

Changes the cleanup from two nested for loops (the 2nd being the unsubscribe_from method), to a single loop with (the common case) deleting a single key from a dict.

We found that with a sufficient number of disconnected clients, and long gaps between database activity, the cleanup could end up taking multiple hours. This would cause the python web service to become unresponsive.

Move subscription tracking to a dict keyed by the underlying websocket object.

Changes the cleanup from two nested for loops (the 2nd being the
unsubscribe_from method), to a single loop with (the common case) deleting a
single key from a dict.
@savingoyal savingoyal requested a review from saikonen June 17, 2024 19:25
@savingoyal
Copy link
Collaborator

lgtm! we can ship this once @saikonen approves

@marshallbrekka
Copy link
Author

@savingoyal @saikonen is there any update here, anything I can do to help get this upstreamed? thanks!

Copy link
Collaborator

@saikonen saikonen left a comment

Choose a reason for hiding this comment

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

overall changes look good. had one minor note on the filter part.

linter step is failing due to unrelated reasons, this is fixed in master now if you want to rebase

# This is primarily useful when calling `unsubscribe_from` during the cleanup
# loop in the event handler.
for k in list(self._subscriptions.keys()):
for sub in self._subscriptions[k]:
Copy link
Collaborator

Choose a reason for hiding this comment

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

note to self: no KeyError possible due to self._subscriptions being a defaultdict(list)

self.subscriptions = list(
filter(lambda s: uuid != s.uuid or ws != s.ws, self.subscriptions))
self._subscriptions[ws] = list(
filter(lambda s: uuid != s.uuid or ws != s.ws, self._subscriptions[ws]))
Copy link
Collaborator

Choose a reason for hiding this comment

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

is the ws != s.ws check necessary anymore as the subscription is keyed per websocket?

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