feat: significantly speed up writing outgoing dns records (#1260) · python-zeroconf/python-zeroconf@bf2f366
@@ -22,6 +22,7 @@
22222323import enum
2424import logging
25+from struct import Struct
2526from typing import TYPE_CHECKING, Dict, List, Optional, Sequence, Tuple, Union
26272728from .._cache import DNSCache
@@ -43,10 +44,16 @@
4344str_ = str
4445float_ = float
4546int_ = int
47+bytes_ = bytes
4648DNSQuestion_ = DNSQuestion
4749DNSRecord_ = DNSRecord
4850495152+PACK_BYTE = Struct('>B').pack
53+PACK_SHORT = Struct('>H').pack
54+PACK_LONG = Struct('>L').pack
55+56+5057class State(enum.Enum):
5158init = 0
5259finished = 1
@@ -200,35 +207,35 @@ def add_question_or_all_cache(
200207201208def _write_byte(self, value: int_) -> None:
202209"""Writes a single byte to the packet"""
203-self.data.append(value.to_bytes(1, 'big'))
210+self.data.append(PACK_BYTE(value))
204211self.size += 1
205212206213def _insert_short_at_start(self, value: int_) -> None:
207214"""Inserts an unsigned short at the start of the packet"""
208-self.data.insert(0, value.to_bytes(2, 'big'))
215+self.data.insert(0, PACK_SHORT(value))
209216210217def _replace_short(self, index: int_, value: int_) -> None:
211218"""Replaces an unsigned short in a certain position in the packet"""
212-self.data[index] = value.to_bytes(2, 'big')
219+self.data[index] = PACK_SHORT(value)
213220214221def write_short(self, value: int_) -> None:
215222"""Writes an unsigned short to the packet"""
216-self.data.append(value.to_bytes(2, 'big'))
223+self.data.append(PACK_SHORT(value))
217224self.size += 2
218225219226def _write_int(self, value: Union[float, int]) -> None:
220227"""Writes an unsigned integer to the packet"""
221-self.data.append(int(value).to_bytes(4, 'big'))
228+self.data.append(PACK_LONG(int(value)))
222229self.size += 4
223230224-def write_string(self, value: bytes) -> None:
231+def write_string(self, value: bytes_) -> None:
225232"""Writes a string to the packet"""
226233if TYPE_CHECKING:
227234assert isinstance(value, bytes)
228235self.data.append(value)
229236self.size += len(value)
230237231-def _write_utf(self, s: str) -> None:
238+def _write_utf(self, s: str_) -> None:
232239"""Writes a UTF-8 string of a given length to the packet"""
233240utfstr = s.encode('utf-8')
234241length = len(utfstr)
@@ -446,7 +453,8 @@ def _packets(self) -> List[bytes]:
446453questions_offset, answer_offset, authority_offset, additional_offset
447454 ):
448455# https://datatracker.ietf.org/doc/html/rfc6762#section-7.2
449-log.debug("Setting TC flag")
456+if debug_enable: # pragma: no branch
457+log.debug("Setting TC flag")
450458self._insert_short_at_start(self.flags | _FLAGS_TC)
451459else:
452460self._insert_short_at_start(self.flags)
@@ -459,9 +467,13 @@ def _packets(self) -> List[bytes]:
459467self.packets_data.append(b''.join(self.data))
460468self._reset_for_next_packet()
461469462-if (questions_written + answers_written + authorities_written + additionals_written) == 0 and (
463-len(self.questions) + len(self.answers) + len(self.authorities) + len(self.additionals)
464- ) > 0:
470+if (
471+not questions_written
472+and not answers_written
473+and not authorities_written
474+and not additionals_written
475+and (self.questions or self.answers or self.authorities or self.additionals)
476+ ):
465477log.warning("packets() made no progress adding records; returning")
466478break
467479self.state = State.finished