From cffbaa1361b535dbccb8b73bca16042a207bb703 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 22 Jan 2025 11:34:57 -1000 Subject: [PATCH 1/3] feat: speed up adding records to the DNSCache --- src/zeroconf/_cache.pxd | 4 +++- src/zeroconf/_cache.py | 11 +++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/zeroconf/_cache.pxd b/src/zeroconf/_cache.pxd index a39ed756..aeaff372 100644 --- a/src/zeroconf/_cache.pxd +++ b/src/zeroconf/_cache.pxd @@ -57,8 +57,10 @@ cdef class DNSCache: @cython.locals( store=cython.dict, + service_store=cython.dict, service_record=DNSService, - when=object + when=object, + new=bint ) cdef bint _async_add(self, DNSRecord record) diff --git a/src/zeroconf/_cache.py b/src/zeroconf/_cache.py index a43bdc5c..02e49dac 100644 --- a/src/zeroconf/_cache.py +++ b/src/zeroconf/_cache.py @@ -86,7 +86,10 @@ def _async_add(self, record: _DNSRecord) -> bool: # replaces any existing records that are __eq__ to each other which # removes the risk that accessing the cache from the wrong # direction would return the old incorrect entry. - store = self.cache.setdefault(record.key, {}) + if record.key not in self.cache: + store = self.cache[record.key] = {} + else: + store = self.cache[record.key] new = record not in store and not isinstance(record, DNSNsec) store[record] = record when = record.created + (record.ttl * 1000) @@ -97,7 +100,11 @@ def _async_add(self, record: _DNSRecord) -> bool: if isinstance(record, DNSService): service_record = record - self.service_cache.setdefault(record.server_key, {})[service_record] = service_record + if service_record.server_key not in self.service_cache: + service_store = self.service_cache[service_record.server_key] = {} + else: + service_store = self.service_cache[service_record.server_key] + service_store[service_record] = service_record return new def async_add_records(self, entries: Iterable[DNSRecord]) -> bool: From a05695d4cf384fbd0f850a64a74bb3eb68d5ab00 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 22 Jan 2025 11:37:09 -1000 Subject: [PATCH 2/3] feat: speed up adding records to the DNSCache --- src/zeroconf/_cache.pxd | 2 +- src/zeroconf/_cache.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/zeroconf/_cache.pxd b/src/zeroconf/_cache.pxd index aeaff372..273d46c3 100644 --- a/src/zeroconf/_cache.pxd +++ b/src/zeroconf/_cache.pxd @@ -39,7 +39,7 @@ cdef class DNSCache: @cython.locals(store=cython.dict) cpdef DNSRecord async_get_unique(self, DNSRecord entry) - @cython.locals(record=DNSRecord) + @cython.locals(record=DNSRecord, when_record=tuple, when=double) cpdef list async_expire(self, double now) @cython.locals(records=cython.dict, record=DNSRecord) diff --git a/src/zeroconf/_cache.py b/src/zeroconf/_cache.py index 02e49dac..521cd7d6 100644 --- a/src/zeroconf/_cache.py +++ b/src/zeroconf/_cache.py @@ -152,7 +152,8 @@ def async_expire(self, now: _float) -> List[DNSRecord]: expired: List[DNSRecord] = [] # Find any expired records and add them to the to-delete list while self._expire_heap: - when, record = self._expire_heap[0] + when_record = self._expire_heap[0] + when = when_record[0] if when > now: break heappop(self._expire_heap) @@ -160,6 +161,7 @@ def async_expire(self, now: _float) -> List[DNSRecord]: # with a different expiration time as it will be removed # later when it reaches the top of the heap and its # expiration time is met. + record = when_record[1] if self._expirations.get(record) == when: expired.append(record) From e7efb1ae215c73bef58207e39cb73599ade8a06c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 22 Jan 2025 12:04:42 -1000 Subject: [PATCH 3/3] chore: refactor --- src/zeroconf/_cache.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/zeroconf/_cache.py b/src/zeroconf/_cache.py index 521cd7d6..1b7aae38 100644 --- a/src/zeroconf/_cache.py +++ b/src/zeroconf/_cache.py @@ -86,10 +86,8 @@ def _async_add(self, record: _DNSRecord) -> bool: # replaces any existing records that are __eq__ to each other which # removes the risk that accessing the cache from the wrong # direction would return the old incorrect entry. - if record.key not in self.cache: + if (store := self.cache.get(record.key)) is None: store = self.cache[record.key] = {} - else: - store = self.cache[record.key] new = record not in store and not isinstance(record, DNSNsec) store[record] = record when = record.created + (record.ttl * 1000) @@ -100,10 +98,8 @@ def _async_add(self, record: _DNSRecord) -> bool: if isinstance(record, DNSService): service_record = record - if service_record.server_key not in self.service_cache: + if (service_store := self.service_cache.get(service_record.server_key)) is None: service_store = self.service_cache[service_record.server_key] = {} - else: - service_store = self.service_cache[service_record.server_key] service_store[service_record] = service_record return new