1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
|
"""Benchark parsing WebSocket handshake requests."""
# The parser for responses is designed similarly and should perform similarly.
import sys
import timeit
from websockets.http11 import Request
from websockets.streams import StreamReader
CHROME_HANDSHAKE = (
b"GET / HTTP/1.1\r\n"
b"Host: localhost:5678\r\n"
b"Connection: Upgrade\r\n"
b"Pragma: no-cache\r\n"
b"Cache-Control: no-cache\r\n"
b"User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
b"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36\r\n"
b"Upgrade: websocket\r\n"
b"Origin: null\r\n"
b"Sec-WebSocket-Version: 13\r\n"
b"Accept-Encoding: gzip, deflate, br\r\n"
b"Accept-Language: en-GB,en;q=0.9,en-US;q=0.8,fr;q=0.7\r\n"
b"Sec-WebSocket-Key: ebkySAl+8+e6l5pRKTMkyQ==\r\n"
b"Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r\n"
b"\r\n"
)
FIREFOX_HANDSHAKE = (
b"GET / HTTP/1.1\r\n"
b"Host: localhost:5678\r\n"
b"User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) "
b"Gecko/20100101 Firefox/111.0\r\n"
b"Accept: */*\r\n"
b"Accept-Language: en-US,en;q=0.7,fr-FR;q=0.3\r\n"
b"Accept-Encoding: gzip, deflate, br\r\n"
b"Sec-WebSocket-Version: 13\r\n"
b"Origin: null\r\n"
b"Sec-WebSocket-Extensions: permessage-deflate\r\n"
b"Sec-WebSocket-Key: 1PuS+hnb+0AXsL7z2hNAhw==\r\n"
b"Connection: keep-alive, Upgrade\r\n"
b"Sec-Fetch-Dest: websocket\r\n"
b"Sec-Fetch-Mode: websocket\r\n"
b"Sec-Fetch-Site: cross-site\r\n"
b"Pragma: no-cache\r\n"
b"Cache-Control: no-cache\r\n"
b"Upgrade: websocket\r\n"
b"\r\n"
)
WEBSOCKETS_HANDSHAKE = (
b"GET / HTTP/1.1\r\n"
b"Host: localhost:8765\r\n"
b"Upgrade: websocket\r\n"
b"Connection: Upgrade\r\n"
b"Sec-WebSocket-Key: 9c55e0/siQ6tJPCs/QR8ZA==\r\n"
b"Sec-WebSocket-Version: 13\r\n"
b"Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r\n"
b"User-Agent: Python/3.11 websockets/11.0\r\n"
b"\r\n"
)
def parse_handshake(handshake):
reader = StreamReader()
reader.feed_data(handshake)
parser = Request.parse(reader.read_line)
try:
next(parser)
except StopIteration:
pass
else:
raise AssertionError("parser should return request")
reader.feed_eof()
assert reader.at_eof(), "parser should consume all data"
def run_benchmark(name, handshake, number=10000):
ph = (
min(
timeit.repeat(
"parse_handshake(handshake)",
number=number,
globals={"parse_handshake": parse_handshake, "handshake": handshake},
)
)
/ number
* 1_000_000
)
print(f"{name}\t{len(handshake)}\t{ph:.1f}")
if __name__ == "__main__":
print("Sizes are in bytes. Times are in µs per frame.", file=sys.stderr)
print("Run `tabs -16` for clean output. Pipe stdout to TSV for saving.")
print(file=sys.stderr)
print("client\tsize\ttime")
run_benchmark("Chrome", CHROME_HANDSHAKE)
run_benchmark("Firefox", FIREFOX_HANDSHAKE)
run_benchmark("websockets", WEBSOCKETS_HANDSHAKE)
|