Skip to content

Commit

Permalink
Speed up removing MQTT subscriptions
Browse files Browse the repository at this point in the history
Currently removing a subscriptions requires a linear search of the
list to find the item. Since mqtt relies on delivering the
subscriptions in order, we cannot use a set since the order
of iterating it is undefined. Instead use a dict with all
True keys since insert order is preserved and removing a key
is O(1) in most cases
  • Loading branch information
bdraco committed May 25, 2024
1 parent d71c770 commit 3afdc0b
Showing 1 changed file with 9 additions and 9 deletions.
18 changes: 9 additions & 9 deletions homeassistant/components/mqtt/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import socket
import ssl
import time
from typing import TYPE_CHECKING, Any
from typing import TYPE_CHECKING, Any, Literal
import uuid

import certifi
Expand Down Expand Up @@ -429,10 +429,10 @@ def __init__(
self.config_entry = config_entry
self.conf = conf

self._simple_subscriptions: defaultdict[str, list[Subscription]] = defaultdict(
list
)
self._wildcard_subscriptions: list[Subscription] = []
self._simple_subscriptions: defaultdict[
str, dict[Subscription, Literal[True]]
] = defaultdict(dict)
self._wildcard_subscriptions: dict[Subscription, Literal[True]] = {}
# _retained_topics prevents a Subscription from receiving a
# retained message more than once per topic. This prevents flooding
# already active subscribers when new subscribers subscribe to a topic
Expand Down Expand Up @@ -789,9 +789,9 @@ def _async_track_subscription(self, subscription: Subscription) -> None:
The caller is responsible clearing the cache of _matching_subscriptions.
"""
if subscription.is_simple_match:
self._simple_subscriptions[subscription.topic].append(subscription)
self._simple_subscriptions[subscription.topic][subscription] = True
else:
self._wildcard_subscriptions.append(subscription)
self._wildcard_subscriptions[subscription] = True

@callback
def _async_untrack_subscription(self, subscription: Subscription) -> None:
Expand All @@ -805,11 +805,11 @@ def _async_untrack_subscription(self, subscription: Subscription) -> None:
try:
if subscription.is_simple_match:
simple_subscriptions = self._simple_subscriptions
simple_subscriptions[topic].remove(subscription)
del simple_subscriptions[topic][subscription]
if not simple_subscriptions[topic]:
del simple_subscriptions[topic]
else:
self._wildcard_subscriptions.remove(subscription)
del self._wildcard_subscriptions[subscription]
except (KeyError, ValueError) as exc:
raise HomeAssistantError("Can't remove subscription twice") from exc

Expand Down

0 comments on commit 3afdc0b

Please sign in to comment.