Skip to content

Commit 2d3aed3

Browse files
authored
feat: speed up answering queries (#1255)
1 parent 5c884b0 commit 2d3aed3

5 files changed

Lines changed: 85 additions & 14 deletions

File tree

build_ext.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ def build(setup_kwargs: Any) -> None:
3030
"src/zeroconf/_protocol/incoming.py",
3131
"src/zeroconf/_protocol/outgoing.py",
3232
"src/zeroconf/_handlers/record_manager.py",
33+
"src/zeroconf/_handlers/query_handler.py",
3334
"src/zeroconf/_services/registry.py",
3435
"src/zeroconf/_utils/time.py",
3536
],
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
2+
import cython
3+
4+
from .._cache cimport DNSCache
5+
from .._dns cimport DNSPointer, DNSQuestion, DNSRecord, DNSRRSet
6+
from .._history cimport QuestionHistory
7+
from .._protocol.incoming cimport DNSIncoming
8+
from .._services.registry cimport ServiceRegistry
9+
10+
11+
cdef object TYPE_CHECKING, QuestionAnswers
12+
cdef cython.uint _ONE_SECOND, _TYPE_PTR, _TYPE_ANY, _TYPE_A, _TYPE_AAAA, _TYPE_SRV, _TYPE_TXT
13+
cdef str _SERVICE_TYPE_ENUMERATION_NAME
14+
cdef cython.set _RESPOND_IMMEDIATE_TYPES
15+
16+
cdef class _QueryResponse:
17+
18+
cdef object _is_probe
19+
cdef DNSIncoming _msg
20+
cdef float _now
21+
cdef DNSCache _cache
22+
cdef cython.dict _additionals
23+
cdef cython.set _ucast
24+
cdef cython.set _mcast_now
25+
cdef cython.set _mcast_aggregate
26+
cdef cython.set _mcast_aggregate_last_second
27+
28+
cpdef add_qu_question_response(self, cython.dict answers)
29+
30+
cpdef add_ucast_question_response(self, cython.dict answers)
31+
32+
cpdef add_mcast_question_response(self, cython.dict answers)
33+
34+
@cython.locals(maybe_entry=DNSRecord)
35+
cpdef _has_mcast_within_one_quarter_ttl(self, DNSRecord record)
36+
37+
@cython.locals(maybe_entry=DNSRecord)
38+
cpdef _has_mcast_record_in_last_second(self, DNSRecord record)
39+
40+
cpdef answers(self)
41+
42+
cdef class QueryHandler:
43+
44+
cdef ServiceRegistry registry
45+
cdef DNSCache cache
46+
cdef QuestionHistory question_history
47+
48+
cdef _add_service_type_enumeration_query_answers(self, cython.dict answer_set, DNSRRSet known_answers)
49+
50+
cdef _add_pointer_answers(self, str lower_name, cython.dict answer_set, DNSRRSet known_answers)
51+
52+
cdef _add_address_answers(self, str lower_name, cython.dict answer_set, DNSRRSet known_answers, cython.uint type_)
53+
54+
@cython.locals(question_lower_name=str, type_=cython.uint)
55+
cdef _answer_question(self, DNSQuestion question, DNSRRSet known_answers)
56+
57+
@cython.locals(
58+
msg=DNSIncoming,
59+
question=DNSQuestion,
60+
answer_set=cython.dict,
61+
known_answers=DNSRRSet,
62+
known_answers_set=cython.set,
63+
)
64+
cpdef async_response(self, cython.list msgs, object unicast_source)

src/zeroconf/_handlers/query_handler.py

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646

4747
_RESPOND_IMMEDIATE_TYPES = {_TYPE_NSEC, _TYPE_SRV, *_ADDRESS_RECORD_TYPES}
4848

49+
_int = int
50+
4951

5052
class _QueryResponse:
5153
"""A pair for unicast and multicast DNSOutgoing responses."""
@@ -113,17 +115,11 @@ def answers(
113115
self,
114116
) -> QuestionAnswers:
115117
"""Return answer sets that will be queued."""
116-
return QuestionAnswers(
117-
*(
118-
{record: self._additionals[record] for record in rrset}
119-
for rrset in (
120-
self._ucast,
121-
self._mcast_now,
122-
self._mcast_aggregate,
123-
self._mcast_aggregate_last_second,
124-
)
125-
)
126-
)
118+
ucast = {r: self._additionals[r] for r in self._ucast}
119+
mcast_now = {r: self._additionals[r] for r in self._mcast_now}
120+
mcast_aggregate = {r: self._additionals[r] for r in self._mcast_aggregate}
121+
mcast_aggregate_last_second = {r: self._additionals[r] for r in self._mcast_aggregate_last_second}
122+
return QuestionAnswers(ucast, mcast_now, mcast_aggregate, mcast_aggregate_last_second)
127123

128124
def _has_mcast_within_one_quarter_ttl(self, record: DNSRecord) -> bool:
129125
"""Check to see if a record has been mcasted recently.
@@ -197,7 +193,7 @@ def _add_address_answers(
197193
lower_name: str,
198194
answer_set: _AnswerWithAdditionalsType,
199195
known_answers: DNSRRSet,
200-
type_: int,
196+
type_: _int,
201197
) -> None:
202198
"""Answer A/AAAA/ANY question."""
203199
for service in self.registry.async_get_infos_server(lower_name):

src/zeroconf/_history.pxd

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
import cython
22

3+
from ._dns cimport DNSQuestion
4+
35

46
cdef cython.double _DUPLICATE_QUESTION_INTERVAL
57

68
cdef class QuestionHistory:
79

810
cdef cython.dict _history
911

12+
cpdef add_question_at_time(self, DNSQuestion question, float now, cython.set known_answers)
1013

1114
@cython.locals(than=cython.double, previous_question=cython.tuple, previous_known_answers=cython.set)
12-
cpdef suppresses(self, object question, cython.double now, cython.set known_answers)
13-
15+
cpdef suppresses(self, DNSQuestion question, cython.double now, cython.set known_answers)
1416

1517
@cython.locals(than=cython.double, now_known_answers=cython.tuple)
1618
cpdef async_expire(self, cython.double now)

src/zeroconf/_services/registry.pxd

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,11 @@ cdef class ServiceRegistry:
1616
cdef _add(self, object info)
1717

1818
cdef _remove(self, cython.list infos)
19+
20+
cpdef async_get_info_name(self, str name)
21+
22+
cpdef async_get_types(self)
23+
24+
cpdef async_get_infos_type(self, str type_)
25+
26+
cpdef async_get_infos_server(self, str server)

0 commit comments

Comments
 (0)