python-websockets / websockets

Library for building WebSocket servers and clients in Python
https://websockets.readthedocs.io/
BSD 3-Clause "New" or "Revised" License
5.23k stars 519 forks source link

Rewrite sync Assembler to improve performance. #1530

Closed aaugustin closed 4 weeks ago

aaugustin commented 4 weeks ago

Previously, a latch was used to synchronize the user thread reading messages and the background thread reading from the network. This required two thread switches per message.

Now, the background thread writes messages to queue, from which the user thread reads. This allows passing several frames at each thread switch, reducing the overhead.

With this server code::

async def test(websocket):
    for i in range(int(await websocket.recv())):
        await websocket.send(f"{{\"iteration\": {i}}}")

and this client code::

with connect("ws://localhost:8765", compression=None) as websocket:
    websocket.send("1_000_000")
    for message in websocket:
        pass

an unscientific benchmark (running it on my laptop) shows a 2.5x speedup, going from 11 seconds to 4.4 seconds. Setting a very large recv_bufsize and max_size doesn't yield significant further improvement.

The new implementation mirrors the asyncio implementation and gains the option to prevent or force decoding of frames. Refs #1376.