Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit b65e279

Browse filesBrowse files
authored
feat: improve performance of processing incoming records (#1155)
1 parent 6abeb78 commit b65e279
Copy full SHA for b65e279

File tree

5 files changed

+32
-29
lines changed
Filter options

5 files changed

+32
-29
lines changed

‎src/zeroconf/_dns.pxd

Copy file name to clipboardExpand all lines: src/zeroconf/_dns.pxd
+6-1Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ cdef object _RECENT_TIME_MS
1616
cdef object _CLASS_UNIQUE
1717
cdef object _CLASS_MASK
1818

19+
cdef object current_time_millis
20+
1921
cdef class DNSEntry:
2022

2123
cdef public object key
@@ -96,8 +98,11 @@ cdef class DNSNsec(DNSRecord):
9698

9799
cdef class DNSRRSet:
98100

99-
cdef _records
101+
cdef _record_sets
100102
cdef cython.dict _lookup
101103

102104
@cython.locals(other=DNSRecord)
103105
cpdef suppresses(self, DNSRecord record)
106+
107+
@cython.locals(lookup=cython.dict)
108+
cdef _get_lookup(self)

‎src/zeroconf/_dns.py

Copy file name to clipboardExpand all lines: src/zeroconf/_dns.py
+17-18Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -512,31 +512,30 @@ def __repr__(self) -> str:
512512

513513

514514
class DNSRRSet:
515-
"""A set of dns records independent of the ttl."""
515+
"""A set of dns records with a lookup to get the ttl."""
516516

517-
__slots__ = ('_records', '_lookup')
517+
__slots__ = ('_record_sets', '_lookup')
518518

519-
def __init__(self, records: Iterable[DNSRecord]) -> None:
520-
"""Create an RRset from records."""
521-
self._records = records
522-
self._lookup: Optional[Dict[DNSRecord, DNSRecord]] = None
519+
def __init__(self, record_sets: Iterable[List[DNSRecord]]) -> None:
520+
"""Create an RRset from records sets."""
521+
self._record_sets = record_sets
522+
self._lookup: Optional[Dict[DNSRecord, float]] = None
523523

524524
@property
525-
def lookup(self) -> Dict[DNSRecord, DNSRecord]:
525+
def lookup(self) -> Dict[DNSRecord, float]:
526+
"""Return the lookup table."""
527+
return self._get_lookup()
528+
529+
def _get_lookup(self) -> Dict[DNSRecord, float]:
530+
"""Return the lookup table, building it if needed."""
526531
if self._lookup is None:
527-
# Build the hash table so we can lookup the record independent of the ttl
528-
self._lookup = {record: record for record in self._records}
532+
# Build the hash table so we can lookup the record ttl
533+
self._lookup = {record: record.ttl for record_sets in self._record_sets for record in record_sets}
529534
return self._lookup
530535

531536
def suppresses(self, record: _DNSRecord) -> bool:
532537
"""Returns true if any answer in the rrset can suffice for the
533538
information held in this record."""
534-
if self._lookup is None:
535-
other = self.lookup.get(record)
536-
else:
537-
other = self._lookup.get(record)
538-
return bool(other and other.ttl > (record.ttl / 2))
539-
540-
def __contains__(self, record: DNSRecord) -> bool:
541-
"""Returns true if the rrset contains the record."""
542-
return record in self.lookup
539+
lookup = self._get_lookup()
540+
other_ttl = lookup.get(record)
541+
return bool(other_ttl and other_ttl > (record.ttl / 2))

‎src/zeroconf/_handlers.py

Copy file name to clipboardExpand all lines: src/zeroconf/_handlers.py
+2-8Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,6 @@ class AnswerGroup(NamedTuple):
9090
answers: _AnswerWithAdditionalsType
9191

9292

93-
def _message_is_probe(msg: DNSIncoming) -> bool:
94-
return msg.num_authorities > 0
95-
96-
9793
def construct_nsec_record(name: str, types: List[int], now: float) -> DNSNsec:
9894
"""Construct an NSEC record for name and a list of dns types.
9995
@@ -159,7 +155,7 @@ class _QueryResponse:
159155

160156
def __init__(self, cache: DNSCache, msgs: List[DNSIncoming]) -> None:
161157
"""Build a query response."""
162-
self._is_probe = any(_message_is_probe(msg) for msg in msgs)
158+
self._is_probe = any(msg.is_probe for msg in msgs)
163159
self._msg = msgs[0]
164160
self._now = self._msg.now
165161
self._cache = cache
@@ -363,9 +359,7 @@ def async_response( # pylint: disable=unused-argument
363359
This function must be run in the event loop as it is not
364360
threadsafe.
365361
"""
366-
known_answers = DNSRRSet(
367-
itertools.chain.from_iterable(msg.answers for msg in msgs if not _message_is_probe(msg))
368-
)
362+
known_answers = DNSRRSet(msg.answers for msg in msgs if not msg.is_probe)
369363
query_res = _QueryResponse(self.cache, msgs)
370364

371365
for msg in msgs:

‎src/zeroconf/_protocol/incoming.py

Copy file name to clipboardExpand all lines: src/zeroconf/_protocol/incoming.py
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,11 @@ def answers(self) -> List[DNSRecord]:
174174
)
175175
return self._answers
176176

177+
@property
178+
def is_probe(self) -> bool:
179+
"""Returns true if this is a probe."""
180+
return self.num_authorities > 0
181+
177182
def __repr__(self) -> str:
178183
return '<DNSIncoming:{%s}>' % ', '.join(
179184
[

‎tests/test_dns.py

Copy file name to clipboardExpand all lines: tests/test_dns.py
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ def test_rrset_does_not_consider_ttl():
392392
longaaaarec = r.DNSAddress('irrelevant', const._TYPE_AAAA, const._CLASS_IN, 100, b'same')
393393
shortaaaarec = r.DNSAddress('irrelevant', const._TYPE_AAAA, const._CLASS_IN, 10, b'same')
394394

395-
rrset = DNSRRSet([longarec, shortaaaarec])
395+
rrset = DNSRRSet([[longarec, shortaaaarec]])
396396

397397
assert rrset.suppresses(longarec)
398398
assert rrset.suppresses(shortarec)
@@ -404,7 +404,7 @@ def test_rrset_does_not_consider_ttl():
404404
mediumarec = r.DNSAddress('irrelevant', const._TYPE_A, const._CLASS_IN, 60, b'same')
405405
shortarec = r.DNSAddress('irrelevant', const._TYPE_A, const._CLASS_IN, 10, b'same')
406406

407-
rrset2 = DNSRRSet([mediumarec])
407+
rrset2 = DNSRRSet([[mediumarec]])
408408
assert not rrset2.suppresses(verylongarec)
409409
assert rrset2.suppresses(longarec)
410410
assert rrset2.suppresses(mediumarec)

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.