From d24722bfa4201d48ab482d35b0ef004f070ada80 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 13 Sep 2023 22:26:08 -0500 Subject: [PATCH] feat: speed up question and answer internals (#1272) --- src/zeroconf/_dns.pxd | 8 ++--- src/zeroconf/_dns.py | 6 ++-- src/zeroconf/_handlers/answers.pxd | 17 +++++++++++ src/zeroconf/_handlers/answers.py | 37 +++++++++++++++++------- src/zeroconf/_handlers/query_handler.pxd | 17 ++++++----- 5 files changed, 61 insertions(+), 24 deletions(-) diff --git a/src/zeroconf/_dns.pxd b/src/zeroconf/_dns.pxd index afcb1985..2e9b778e 100644 --- a/src/zeroconf/_dns.pxd +++ b/src/zeroconf/_dns.pxd @@ -22,8 +22,8 @@ cdef object current_time_millis cdef class DNSEntry: - cdef public object key - cdef public object name + cdef public str key + cdef public str name cdef public object type cdef public object class_ cdef public object unique @@ -84,8 +84,8 @@ cdef class DNSHinfo(DNSRecord): cdef class DNSPointer(DNSRecord): cdef public cython.int _hash - cdef public object alias - cdef public object alias_key + cdef public str alias + cdef public str alias_key cdef _eq(self, DNSPointer other) diff --git a/src/zeroconf/_dns.py b/src/zeroconf/_dns.py index 4c015eb3..b546d273 100644 --- a/src/zeroconf/_dns.py +++ b/src/zeroconf/_dns.py @@ -67,9 +67,9 @@ class DNSEntry: __slots__ = ('key', 'name', 'type', 'class_', 'unique') - def __init__(self, name: str, type_: int, class_: int) -> None: - self.key = name.lower() + def __init__(self, name: str, type_: _int, class_: _int) -> None: self.name = name + self.key = name.lower() self.type = type_ self.class_ = class_ & _CLASS_MASK self.unique = (class_ & _CLASS_UNIQUE) != 0 @@ -328,7 +328,7 @@ def __init__( ) -> None: super().__init__(name, type_, class_, ttl, created) self.alias = alias - self.alias_key = self.alias.lower() + self.alias_key = alias.lower() self._hash = hash((self.key, type_, self.class_, self.alias_key)) @property diff --git a/src/zeroconf/_handlers/answers.pxd b/src/zeroconf/_handlers/answers.pxd index 91e2375d..6a0f0e3d 100644 --- a/src/zeroconf/_handlers/answers.pxd +++ b/src/zeroconf/_handlers/answers.pxd @@ -5,6 +5,23 @@ from .._dns cimport DNSRecord from .._protocol.outgoing cimport DNSOutgoing +cdef class QuestionAnswers: + + cdef public object ucast + cdef public object mcast_now + cdef public object mcast_aggregate + cdef public object mcast_aggregate_last_second + + +cdef class AnswerGroup: + + cdef public object send_after + cdef public object send_before + cdef public object answers + + + + cdef object _FLAGS_QR_RESPONSE_AA cdef object NAME_GETTER diff --git a/src/zeroconf/_handlers/answers.py b/src/zeroconf/_handlers/answers.py index 009bedbc..6ba502ac 100644 --- a/src/zeroconf/_handlers/answers.py +++ b/src/zeroconf/_handlers/answers.py @@ -21,7 +21,7 @@ """ from operator import attrgetter -from typing import Dict, List, NamedTuple, Set +from typing import Dict, List, Set from .._dns import DNSQuestion, DNSRecord from .._protocol.outgoing import DNSOutgoing @@ -38,20 +38,37 @@ _FLAGS_QR_RESPONSE_AA = _FLAGS_QR_RESPONSE | _FLAGS_AA +float_ = float -class QuestionAnswers(NamedTuple): - ucast: _AnswerWithAdditionalsType - mcast_now: _AnswerWithAdditionalsType - mcast_aggregate: _AnswerWithAdditionalsType - mcast_aggregate_last_second: _AnswerWithAdditionalsType +class QuestionAnswers: + """A group of answers to a question.""" -class AnswerGroup(NamedTuple): + __slots__ = ('ucast', 'mcast_now', 'mcast_aggregate', 'mcast_aggregate_last_second') + + def __init__( + self, + ucast: _AnswerWithAdditionalsType, + mcast_now: _AnswerWithAdditionalsType, + mcast_aggregate: _AnswerWithAdditionalsType, + mcast_aggregate_last_second: _AnswerWithAdditionalsType, + ) -> None: + """Initialize a QuestionAnswers.""" + self.ucast = ucast + self.mcast_now = mcast_now + self.mcast_aggregate = mcast_aggregate + self.mcast_aggregate_last_second = mcast_aggregate_last_second + + +class AnswerGroup: """A group of answers scheduled to be sent at the same time.""" - send_after: float # Must be sent after this time - send_before: float # Must be sent before this time - answers: _AnswerWithAdditionalsType + __slots__ = ('send_after', 'send_before', 'answers') + + def __init__(self, send_after: float_, send_before: float_, answers: _AnswerWithAdditionalsType) -> None: + self.send_after = send_after # Must be sent after this time + self.send_before = send_before # Must be sent before this time + self.answers = answers def construct_outgoing_multicast_answers(answers: _AnswerWithAdditionalsType) -> DNSOutgoing: diff --git a/src/zeroconf/_handlers/query_handler.pxd b/src/zeroconf/_handlers/query_handler.pxd index 1f1e4da8..31261a69 100644 --- a/src/zeroconf/_handlers/query_handler.pxd +++ b/src/zeroconf/_handlers/query_handler.pxd @@ -2,14 +2,15 @@ import cython from .._cache cimport DNSCache -from .._dns cimport DNSPointer, DNSQuestion, DNSRecord, DNSRRSet +from .._dns cimport DNSAddress, DNSPointer, DNSQuestion, DNSRecord, DNSRRSet from .._history cimport QuestionHistory from .._protocol.incoming cimport DNSIncoming from .._services.info cimport ServiceInfo from .._services.registry cimport ServiceRegistry +from .answers cimport QuestionAnswers -cdef object TYPE_CHECKING, QuestionAnswers +cdef object TYPE_CHECKING cdef cython.uint _ONE_SECOND, _TYPE_PTR, _TYPE_ANY, _TYPE_A, _TYPE_AAAA, _TYPE_SRV, _TYPE_TXT cdef str _SERVICE_TYPE_ENUMERATION_NAME cdef cython.set _RESPOND_IMMEDIATE_TYPES @@ -19,7 +20,7 @@ cdef object _TYPE_PTR, _CLASS_IN, _DNS_OTHER_TTL cdef class _QueryResponse: - cdef object _is_probe + cdef bint _is_probe cdef DNSIncoming _msg cdef float _now cdef DNSCache _cache @@ -29,17 +30,19 @@ cdef class _QueryResponse: cdef cython.set _mcast_aggregate cdef cython.set _mcast_aggregate_last_second + @cython.locals(record=DNSRecord) cpdef add_qu_question_response(self, cython.dict answers) cpdef add_ucast_question_response(self, cython.dict answers) + @cython.locals(answer=DNSRecord) cpdef add_mcast_question_response(self, cython.dict answers) @cython.locals(maybe_entry=DNSRecord) - cpdef _has_mcast_within_one_quarter_ttl(self, DNSRecord record) + cdef bint _has_mcast_within_one_quarter_ttl(self, DNSRecord record) @cython.locals(maybe_entry=DNSRecord) - cpdef _has_mcast_record_in_last_second(self, DNSRecord record) + cdef bint _has_mcast_record_in_last_second(self, DNSRecord record) cpdef answers(self) @@ -55,8 +58,8 @@ cdef class QueryHandler: @cython.locals(service=ServiceInfo) cdef _add_pointer_answers(self, str lower_name, cython.dict answer_set, DNSRRSet known_answers) - @cython.locals(service=ServiceInfo) - cdef _add_address_answers(self, str lower_name, cython.dict answer_set, DNSRRSet known_answers, cython.uint type_) + @cython.locals(service=ServiceInfo, dns_address=DNSAddress) + cdef _add_address_answers(self, str lower_name, cython.dict answer_set, DNSRRSet known_answers, object type_) @cython.locals(question_lower_name=str, type_=cython.uint, service=ServiceInfo) cdef cython.dict _answer_question(self, DNSQuestion question, DNSRRSet known_answers)