RejectedSoftware Forums

Sign up

Safe to call WebSocket.send from multiple Fibres?

In this instance I'm running a chat-like server where users can play and chat together, so for example when one websocket receives a message, the fibre that receives the message might then go off and send that message to other web sockets.

Is it fine to do this or do I need some kinda Task Mutex around the "send" call?

Thanks!

Re: Safe to call WebSocket.send from multiple Fibres?

On 2013-10-21 14:19:56 +0000, James Pike said:

In this instance I'm running a chat-like server where users can play
and chat together, so for example when one websocket receives a
message, the fibre that receives the message might then go off and send
that message to other web sockets.

Is it fine to do this or do I need some kinda Task Mutex around the
"send" call?

Thanks!

You need to send a message to the other thread to pass along. I am
doing something similar:

https://github.com/schancel/gameserver

Re: Safe to call WebSocket.send from multiple Fibres?

Am 22.10.2013 01:39, schrieb Shammah Chancellor:

On 2013-10-21 14:19:56 +0000, James Pike said:

In this instance I'm running a chat-like server where users can play
and chat together, so for example when one websocket receives a
message, the fibre that receives the message might then go off and
send that message to other web sockets.

Is it fine to do this or do I need some kinda Task Mutex around the
"send" call?

Thanks!

You need to send a message to the other thread to pass along. I am
doing something similar:

https://github.com/schancel/gameserver

This is what I would recommend, too (i.e. to use
vibe.core.concurrency.send/recv to send the messages to a dedicated
sender task for each client). This has the advantage that if a single
client has a low quality connection, the other clients will stay unaffected.

Without doing this, you currently do need to use a TaskMutex to
protect writes from different tasks. This requirement may fall at some
point when WebSocket connections get their own internal mutex, but this
is not yet completely decided.

Re: Safe to call WebSocket.send from multiple Fibres?

On Tue, 22 Oct 2013 08:53:01 +0200, Sönke Ludwig wrote:

Am 22.10.2013 01:39, schrieb Shammah Chancellor:

You need to send a message to the other thread to pass along. I am
doing something similar:

https://github.com/schancel/gameserver

This is what I would recommend, too (i.e. to use
vibe.core.concurrency.send/recv to send the messages to a dedicated
sender task for each client). This has the advantage that if a single
client has a low quality connection, the other clients will stay unaffected.

Thanks very much for your responses, I see how it needs to be done :)

Nice work on vibed BTW I really like it. I had to pull the latest websocket code out of git to get sending back to the browser to work, it's totally broken in the .17beta but other than that it's been a fun to work with.

Re: Safe to call WebSocket.send from multiple Fibres?

Am 22.10.2013 01:39, schrieb Shammah Chancellor:

You need to send a message to the other thread to pass along. I am
doing something similar:

https://github.com/schancel/gameserver

Okay cool I modified my code to use this system now, although performance becomes terrible after about 5,000 busy WebSocket connections.

I guess because each Task spawns a real thread and I start getting a lot of context switching. I think to handle thousands of web sockets I'd need to delegate all the web socket writes to a single thread that uses async IO via a system of callbacks rather than fibres for synchronisation so that all writes can occur without blocking each other. Unless anybody can think of a better way...

Re: Safe to call WebSocket.send from multiple Fibres?

Okay the more I look at this the more convinced I am that the only way we're gonna get efficient support for websockets and the kind of things to do with websockets is to change the way vibed works with respect to websockets.

I think using a Fibre per websocket is great, especially when it comes to reading. However when it comes to writing the data back I think the "in fibre" write method should schedule the write using a more traditional libevent architecture based on callbacks. Then other fibres would be able to transparently write to the websocket.

I think this is pretty important... I mean when you consider what web sockets are for it doesn't make sense to only write from one fibre there's always going to be a need to push out data from other fibres/threads and to be able to do that simply and efficiently I think is pretty important for the adoption of a websocket server.

I'm happy to write a patch against vibed if you think this sounds okay?

Re: Safe to call WebSocket.send from multiple Fibres?

Am 22.10.2013 14:07, schrieb James Pike:

Am 22.10.2013 01:39, schrieb Shammah Chancellor:

You need to send a message to the other thread to pass along. I am
doing something similar:

https://github.com/schancel/gameserver

Okay cool I modified my code to use this system now, although performance becomes terrible after about 5,000 busy WebSocket connections.

I guess because each Task spawns a real thread and I start getting a lot of context switching. I think to handle thousands of web sockets I'd need to delegate all the web socket writes to a single thread that uses async IO via a system of callbacks rather than fibres for synchronisation so that all writes can occur without blocking each other. Unless anybody can think of a better way...

It's not a thread per task, but a fiber per task (and fibers are
reused). Context switches of fibers are very fast and shouldn't be the
cause of the bad performance. If you can upload a benchmark/testcase
somewhere, I'd like to take a look at what takes so long.

Re: Safe to call WebSocket.send from multiple Fibres?

On Tue, 22 Oct 2013 17:37:41 +0200, Sönke Ludwig wrote:

It's not a thread per task, but a fiber per task (and fibers are
reused). Context switches of fibers are very fast and shouldn't be the
cause of the bad performance. If you can upload a benchmark/testcase
somewhere, I'd like to take a look at what takes so long.

Ah of course I read a lot more the vibed code now and I get it, thanks for explaining things to me :)

I can't provide the exact code/test benchmark I'm using as this code isn't open source, but I'll try to distill the performance issue into a smaller test case so I can send it along.

Re: Safe to call WebSocket.send from multiple Fibres?

On 2013-10-22 13:14:06 +0000, James Pike said:

Okay the more I look at this the more convinced I am that the only way
we're gonna get efficient support for websockets and the kind of things
to do with websockets is to change the way vibed works with respect to
websockets.

I think using a Fibre per websocket is great, especially when it comes
to reading. However when it comes to writing the data back I think the
"in fibre" write method should schedule the write using a more
traditional libevent architecture based on callbacks. Then other fibres
would be able to transparently write to the websocket.

I think this is pretty important... I mean when you consider what web
sockets are for it doesn't make sense to only write from one fibre
there's always going to be a need to push out data from other
fibres/threads and to be able to do that simply and efficiently I think
is pretty important for the adoption of a websocket server.

I'm happy to write a patch against vibed if you think this sounds okay?

This is sort of what it's doing anyways. My code spawns a fiber which
is basically a callback in D. It yields a delegate to it's current
executing position to the event loop which resumes it at some later
time.
I don't think 5000 concurrent connections is something to scoff at.
That's around half the efficiency of an 50% of what an IRC server does
without any tuning.

It would be preferable to not have the fiber for the sender thread,
since I already have a fiber-per-channel, but this way different
channels don't block each other from writing to the socket and putting
messages in the MessageQueue should be pretty lightweight.

Re: Safe to call WebSocket.send from multiple Fibres?

On 2013-10-22 18:37:29 +0000, James Pike said:

On Tue, 22 Oct 2013 17:37:41 +0200, Sönke Ludwig wrote:

It's not a thread per task, but a fiber per task (and fibers are

reused). Context switches of fibers are very fast and shouldn't be the

cause of the bad performance. If you can upload a benchmark/testcase

somewhere, I'd like to take a look at what takes so long.

Ah of course I read a lot more the vibed code now and I get it, thanks
for explaining things to me :)

I can't provide the exact code/test benchmark I'm using as this code
isn't open source, but I'll try to distill the performance issue into a
smaller test case so I can send it along.

Thanks. I am hoping to get my game server to support around 10k
connections eventually. Right now it doesn't really do anything though
:) I need to add features before I worry too much about speed.