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