feat: optimize cache implementation (#1252) · python-zeroconf/python-zeroconf@8d3ec79

@@ -20,7 +20,6 @@

2020

USA

2121

"""

222223-

import itertools

2423

from typing import Dict, Iterable, List, Optional, Set, Tuple, Union, cast

25242625

from ._dns import (

@@ -115,12 +114,12 @@ def async_remove_records(self, entries: Iterable[DNSRecord]) -> None:

115114

for entry in entries:

116115

self._async_remove(entry)

117116118-

def async_expire(self, now: float) -> List[DNSRecord]:

117+

def async_expire(self, now: _float) -> List[DNSRecord]:

119118

"""Purge expired entries from the cache.

120119121120

This function must be run in from event loop.

122121

"""

123-

expired = [record for record in itertools.chain(*self.cache.values()) if record.is_expired(now)]

122+

expired = [record for records in self.cache.values() for record in records if record.is_expired(now)]

124123

self.async_remove_records(expired)

125124

return expired

126125

@@ -136,15 +135,7 @@ def async_get_unique(self, entry: _UniqueRecordsType) -> Optional[DNSRecord]:

136135

return None

137136

return store.get(entry)

138137139-

def async_all_by_details(self, name: _str, type_: int, class_: int) -> Iterable[DNSRecord]:

140-

"""Gets all matching entries by details.

141-142-

This function is not thread-safe and must be called from

143-

the event loop.

144-

"""

145-

return self._async_all_by_details(name, type_, class_)

146-147-

def _async_all_by_details(self, name: _str, type_: _int, class_: _int) -> List[DNSRecord]:

138+

def async_all_by_details(self, name: _str, type_: _int, class_: _int) -> List[DNSRecord]:

148139

"""Gets all matching entries by details.

149140150141

This function is not thread-safe and must be called from

@@ -240,20 +231,16 @@ def names(self) -> List[str]:

240231241232

def async_mark_unique_records_older_than_1s_to_expire(

242233

self, unique_types: Set[Tuple[_str, _int, _int]], answers: Iterable[DNSRecord], now: _float

243-

) -> None:

244-

self._async_mark_unique_records_older_than_1s_to_expire(unique_types, answers, now)

245-246-

def _async_mark_unique_records_older_than_1s_to_expire(

247-

self, unique_types: Set[Tuple[_str, _int, _int]], answers: Iterable[DNSRecord], now: _float

248234

) -> None:

249235

# rfc6762#section-10.2 para 2

250236

# Since unique is set, all old records with that name, rrtype,

251237

# and rrclass that were received more than one second ago are declared

252238

# invalid, and marked to expire from the cache in one second.

253239

answers_rrset = set(answers)

254240

for name, type_, class_ in unique_types:

255-

for record in self._async_all_by_details(name, type_, class_):

256-

if (now - record.created > _ONE_SECOND) and record not in answers_rrset:

241+

for record in self.async_all_by_details(name, type_, class_):

242+

created_float = record.created

243+

if (now - created_float > _ONE_SECOND) and record not in answers_rrset:

257244

# Expire in 1s

258245

record.set_created_ttl(now, 1)

259246