Skip to content

Commit d3c475f

Browse files
authored
Improve cache of decode labels at offset (python-zeroconf#1097)
1 parent 0989336 commit d3c475f

2 files changed

Lines changed: 170 additions & 1 deletion

File tree

bench/incoming.py

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
"""Benchmark for DNSIncoming."""
2+
import socket
3+
import timeit
4+
5+
from zeroconf import DNSAddress, DNSIncoming, DNSOutgoing, DNSService, DNSText, const
6+
7+
8+
def generate_packets():
9+
out = DNSOutgoing(const._FLAGS_QR_RESPONSE | const._FLAGS_AA)
10+
address = socket.inet_pton(socket.AF_INET, "192.168.208.5")
11+
12+
additionals = [
13+
{
14+
"name": "HASS Bridge ZJWH FF5137._hap._tcp.local.",
15+
"address": address,
16+
"port": 51832,
17+
"text": b"\x13md=HASS Bridge"
18+
b" ZJWH\x06pv=1.0\x14id=01:6B:30:FF:51:37\x05c#=12\x04s#=1\x04ff=0\x04"
19+
b"ci=2\x04sf=0\x0bsh=L0m/aQ==",
20+
},
21+
{
22+
"name": "HASS Bridge 3K9A C2582A._hap._tcp.local.",
23+
"address": address,
24+
"port": 51834,
25+
"text": b"\x13md=HASS Bridge"
26+
b" 3K9A\x06pv=1.0\x14id=E2:AA:5B:C2:58:2A\x05c#=12\x04s#=1\x04ff=0\x04"
27+
b"ci=2\x04sf=0\x0bsh=b2CnzQ==",
28+
},
29+
{
30+
"name": "Master Bed TV CEDB27._hap._tcp.local.",
31+
"address": address,
32+
"port": 51830,
33+
"text": b"\x10md=Master Bed"
34+
b" TV\x06pv=1.0\x14id=9E:B7:44:CE:DB:27\x05c#=18\x04s#=1\x04ff=0\x05"
35+
b"ci=31\x04sf=0\x0bsh=CVj1kw==",
36+
},
37+
{
38+
"name": "Living Room TV 921B77._hap._tcp.local.",
39+
"address": address,
40+
"port": 51833,
41+
"text": b"\x11md=Living Room"
42+
b" TV\x06pv=1.0\x14id=11:61:E7:92:1B:77\x05c#=17\x04s#=1\x04ff=0\x05"
43+
b"ci=31\x04sf=0\x0bsh=qU77SQ==",
44+
},
45+
{
46+
"name": "HASS Bridge ZC8X FF413D._hap._tcp.local.",
47+
"address": address,
48+
"port": 51829,
49+
"text": b"\x13md=HASS Bridge"
50+
b" ZC8X\x06pv=1.0\x14id=96:14:45:FF:41:3D\x05c#=12\x04s#=1\x04ff=0\x04"
51+
b"ci=2\x04sf=0\x0bsh=b0QZlg==",
52+
},
53+
{
54+
"name": "HASS Bridge WLTF 4BE61F._hap._tcp.local.",
55+
"address": address,
56+
"port": 51837,
57+
"text": b"\x13md=HASS Bridge"
58+
b" WLTF\x06pv=1.0\x14id=E0:E7:98:4B:E6:1F\x04c#=2\x04s#=1\x04ff=0\x04"
59+
b"ci=2\x04sf=0\x0bsh=ahAISA==",
60+
},
61+
{
62+
"name": "FrontdoorCamera 8941D1._hap._tcp.local.",
63+
"address": address,
64+
"port": 54898,
65+
"text": b"\x12md=FrontdoorCamera\x06pv=1.0\x14id=9F:B7:DC:89:41:D1\x04c#=2\x04"
66+
b"s#=1\x04ff=0\x04ci=2\x04sf=0\x0bsh=0+MXmA==",
67+
},
68+
{
69+
"name": "HASS Bridge W9DN 5B5CC5._hap._tcp.local.",
70+
"address": address,
71+
"port": 51836,
72+
"text": b"\x13md=HASS Bridge"
73+
b" W9DN\x06pv=1.0\x14id=11:8E:DB:5B:5C:C5\x05c#=12\x04s#=1\x04ff=0\x04"
74+
b"ci=2\x04sf=0\x0bsh=6fLM5A==",
75+
},
76+
{
77+
"name": "HASS Bridge Y9OO EFF0A7._hap._tcp.local.",
78+
"address": address,
79+
"port": 51838,
80+
"text": b"\x13md=HASS Bridge"
81+
b" Y9OO\x06pv=1.0\x14id=D3:FE:98:EF:F0:A7\x04c#=2\x04s#=1\x04ff=0\x04"
82+
b"ci=2\x04sf=0\x0bsh=u3bdfw==",
83+
},
84+
{
85+
"name": "Snooze Room TV 6B89B0._hap._tcp.local.",
86+
"address": address,
87+
"port": 51835,
88+
"text": b"\x11md=Snooze Room"
89+
b" TV\x06pv=1.0\x14id=5F:D5:70:6B:89:B0\x05c#=17\x04s#=1\x04ff=0\x05"
90+
b"ci=31\x04sf=0\x0bsh=xNTqsg==",
91+
},
92+
{
93+
"name": "AlexanderHomeAssistant 74651D._hap._tcp.local.",
94+
"address": address,
95+
"port": 54811,
96+
"text": b"\x19md=AlexanderHomeAssistant\x06pv=1.0\x14id=59:8A:0B:74:65:1D\x05"
97+
b"c#=14\x04s#=1\x04ff=0\x04ci=2\x04sf=0\x0bsh=ccZLPA==",
98+
},
99+
{
100+
"name": "HASS Bridge OS95 39C053._hap._tcp.local.",
101+
"address": address,
102+
"port": 51831,
103+
"text": b"\x13md=HASS Bridge"
104+
b" OS95\x06pv=1.0\x14id=7E:8C:E6:39:C0:53\x05c#=12\x04s#=1\x04ff=0\x04ci=2"
105+
b"\x04sf=0\x0bsh=Xfe5LQ==",
106+
},
107+
]
108+
109+
out.add_answer_at_time(
110+
DNSText(
111+
"HASS Bridge W9DN 5B5CC5._hap._tcp.local.",
112+
const._TYPE_TXT,
113+
const._CLASS_IN | const._CLASS_UNIQUE,
114+
const._DNS_OTHER_TTL,
115+
b'\x13md=HASS Bridge W9DN\x06pv=1.0\x14id=11:8E:DB:5B:5C:C5\x05c#=12\x04s#=1'
116+
b'\x04ff=0\x04ci=2\x04sf=0\x0bsh=6fLM5A==',
117+
),
118+
0,
119+
)
120+
121+
for record in additionals:
122+
out.add_additional_answer(
123+
DNSService(
124+
record["name"], # type: ignore
125+
const._TYPE_SRV,
126+
const._CLASS_IN | const._CLASS_UNIQUE,
127+
const._DNS_HOST_TTL,
128+
0,
129+
0,
130+
record["port"], # type: ignore
131+
record["name"], # type: ignore
132+
)
133+
)
134+
out.add_additional_answer(
135+
DNSText(
136+
record["name"], # type: ignore
137+
const._TYPE_TXT,
138+
const._CLASS_IN | const._CLASS_UNIQUE,
139+
const._DNS_OTHER_TTL,
140+
record["text"], # type: ignore
141+
)
142+
)
143+
out.add_additional_answer(
144+
DNSAddress(
145+
record["name"], # type: ignore
146+
const._TYPE_A,
147+
const._CLASS_IN | const._CLASS_UNIQUE,
148+
const._DNS_HOST_TTL,
149+
record["address"], # type: ignore
150+
)
151+
)
152+
153+
return out.packets()
154+
155+
156+
packets = generate_packets()
157+
158+
159+
def parse_incoming_message():
160+
for packet in packets:
161+
DNSIncoming(packet).answers
162+
break
163+
164+
165+
count = 100000
166+
time = timeit.Timer(parse_incoming_message).timeit(count)
167+
print(f"Parsing {count} incoming messages took {time} seconds")

zeroconf/_protocol/incoming.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,9 @@ def read_name(self) -> str:
271271
"""Reads a domain name from the packet."""
272272
labels: List[str] = []
273273
seen_pointers: Set[int] = set()
274-
self.offset = self._decode_labels_at_offset(self.offset, labels, seen_pointers)
274+
original_offset = self.offset
275+
self.offset = self._decode_labels_at_offset(original_offset, labels, seen_pointers)
276+
self.name_cache[original_offset] = labels
275277
name = ".".join(labels) + "."
276278
if len(name) > MAX_NAME_LENGTH:
277279
raise IncomingDecodeError(

0 commit comments

Comments
 (0)