feat: improve performance of constructing ServiceInfo (#1141) · python-zeroconf/python-zeroconf@36d5b45

@@ -23,6 +23,7 @@

2323

import ipaddress

2424

import random

2525

import socket

26+

from functools import lru_cache

2627

from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set, Union, cast

27282829

from .._dns import (

@@ -79,6 +80,9 @@ def instance_name_from_service_info(info: "ServiceInfo") -> str:

7980

return info.name[: -len(service_name) - 1]

8081818283+

_cached_ip_addresses = lru_cache(maxsize=256)(ipaddress.ip_address)

84+85+8286

class ServiceInfo(RecordUpdateListener):

8387

"""Service information.

8488

@@ -196,7 +200,7 @@ def addresses(self, value: List[bytes]) -> None:

196200197201

for address in value:

198202

try:

199-

addr = ipaddress.ip_address(address)

203+

addr = _cached_ip_addresses(address)

200204

except ValueError:

201205

raise TypeError(

202206

"Addresses must either be IPv4 or IPv6 strings, bytes, or integers;"

@@ -245,7 +249,7 @@ def parsed_scoped_addresses(self, version: IPVersion = IPVersion.All) -> List[st

245249

return self.parsed_addresses(version)

246250247251

def is_link_local(addr_str: str) -> Any:

248-

addr = ipaddress.ip_address(addr_str)

252+

addr = _cached_ip_addresses(addr_str)

249253

return addr.version == 6 and addr.is_link_local

250254251255

ll_addrs = list(filter(is_link_local, self.parsed_addresses(version)))

@@ -346,7 +350,7 @@ def _process_record_threadsafe(self, record: DNSRecord, now: float) -> None:

346350

if record.key != self.server_key:

347351

return

348352

try:

349-

ip_addr = ipaddress.ip_address(record.address)

353+

ip_addr = _cached_ip_addresses(record.address)

350354

except ValueError as ex:

351355

log.warning("Encountered invalid address while processing %s: %s", record, ex)

352356

return