LordOdin
LordOdin

Reputation: 21

Python websockets fast one way but 10x slower with response

I have a sanic webserver running websockets, behind the scenes its using the "websockets" library.

Server

from asyncio import sleep
from sanic import Sanic

app = Sanic("websocket test")

@app.websocket("/")
async def test(_, ws):
    while True:
        data = await ws.recv()
        data = await ws.send('Hi')

if __name__ == "__main__":
    app.run(host="127.0.0.1", port=8000)

Client

import asyncio
import websockets

async def hello():
    uri = "ws://localhost:8000"
    async with websockets.connect(uri) as websocket:
        while iteration:
            await websocket.send("Hi")
            await websocket.recv()

asyncio.get_event_loop().run_until_complete(hello())

When I remove ws.send('Hi') from the server and await websocket.recv() from the client i can get 58000 messages a second, once I start listening for a response it goes all the way down to 6000 messages a second, I am just curious what is making this run 10x slower when the server responds.

Upvotes: 1

Views: 6114

Answers (1)

Adam Hopkins
Adam Hopkins

Reputation: 7102

I think the solution here would be to seperate your send and recv into seperate tasks so they can yield concurrently.

async def producer(send):
    while True:
        await send("...")
        await asyncio.sleep(1)

async def consumer(recv):
    while True:
        message = await recv
        print(message)

async def test(request, ws):
    request.app.add_task(producer(ws.send)))
    request.app.add_task(consumer(ws.recv))

Obviously, this is a very simple example, and at the very least you should use some sort of a Queue for your producer.

But, when you break them into seperate tasks, then your recv is not blocked by send.

Upvotes: 4

Related Questions