The Road to 2M Websocket Connections in Phoenix
phoenixframework.org
phoenixframework.org
Whatsapp famously works with 2m connections on a FreeBSD box (this number is old, I bet they've beaten that number). http://highscalability.com/blog/2014/2/26/the-whatsapp-archi...
I wonder whether these two cases are in any way comparable. Different stacks, different machines, different test. The only similarity being BEAM/Erlang used as a platform. Speaks well of its scalability!
I'm also happy to answer any other questions. The team is very excited about our channel and pubsub layers progress over the last year.
Sometimes someone throws something out so casually and yet you realise the innate sense of what they just said, I literally stopped with coffee halfway to my mouth.
I'd never have thought of doing it that way.
1) outdated, version used is really really old (0.8 or so)
2) Database pool set to really low value unlike other participants (~10x lower)
3) Configured to do many things other frameworks skip, like generating csrf token
All these points were fixed already but, most likely, new results will go to Round 12
But why did you downvote my comment? I was just reporting a fact, a benchmark that was performed by a third-party. It's not like I was voicing a weird opinion or fabricating truth.
In particular DragonflyBSD since it has a lockless network stack.
And FreeBSD for good measure given that Whatsapp runs an Erlang/FreeBSD stack and has documented 2-3M connections themselves.
2M users per machine is great if they are mostly idle. This is the use case of WhatsApp, and their stats are[1]:
> Peaked at 2.8M connections per server
> 571k packets/sec
> >200k dist msgs/sec
Not every app is meant to have mostly idle users. Can a real-time MMO FPS be done in phoenix is the question (lets limit each user's neighbourhood to the 10 closest players).
I'd be very interested in the other corners of the envelope for phoenix: A requests/second benchmark over websockets, with the associated latency HdrHistogram, like [2]
[1] http://highscalability.com/blog/2014/2/26/the-whatsapp-archi...
[2] http://www.ostinelli.net/a-comparison-between-misultin-mochi...
Yes, and the next phase for our tests will explore these kinds of use-cases. To give you an idea, our pubsub layer can support 500k messages/sec on a macbook. These tests were specifically around max clients and max subscribers, but more tests are needed for hard numbers around the usecaes you layed out, which we'll be a great fit for. I think gaming will be huge target for Phoenix.
Not because of Phoenix itself, but because all modern lag-compensating techniques rely on specific properties of UDP that are not implementable over TCP (and thus not over Websockets or HTTP long poll, which are the currently supported Phoenix Channel transports).
Not to diminish the value of Phoenix: the framework is really pleasant to use both on dev side and ops side. And you could use it today to implement the server-side of most games, even some "massive multiplayer" ones, as long as latency is not your primary concern.
The backend channel code remains the same and the transport takes care of the underlying communication details.
For comparison, I checked my not-very-optimized go server, and it looks like (based on VSZ value) to use 25KB per connection in go, with 43KB per connection used by nginx (to provide SSL termination).
Depending on your traffic patterns, considering the broadcast activity is potentially important, and then you might worry more about CPU than RAM.
I use redis myself, but gnatsd or redis cluster may help with scaling the pubsub part of the system.
> The difference between bag and duplicate_bag is that duplicate_bag will allow multiple entries for the same key.
bag also allows multiple entries per key. After reading the ETS documentation, it appears that duplicate_bag allows the same object instance to appear as a value for a key multiple times, whereas bag only allows an object instance to be added once to a key (e.g. so if you add the exact same object instance to the table using a given key, bag will only end up with one value for the key, but duplicate_bag will happily have many identical values for that key).
The following sentence is still fine:
> Since each socket can only connect once and have one pid, using a duplicate bag didn't cause any issues for us.
Like the Pheonix test, this tested broadcast throughput. However we couldn't push more than 5000 messages per second out of a single EC2 m1.xlarge instance otherwise latency would increase. My theory is that we were hitting the maximum throughput of the underlying NIC, causing packet loss and requiring TCP to retransmit (hence the latency). At some point I want to try adding multiple virtual NICs to the same EC2 instance and see if that helps.
i have achieved 500k concurrent connections using atmosphere, consuming around 10gb of ram.
That depends. Two million connections from people in an e-commerce site is a lot, but two million connections for a side-thingy like some analytics/ads/background-job-whatever doesn't have to be that much, especially if you consider 3rd party code.
I'm just wondering where is the per-connection overhead going into. Is there some inherent limitation of the WebSocket protocol that forces the server to keep large buffers or something? Not trying to bash on Phoenix, I'm just genuinely interested in what is the lowest possible overhead one could achieve while keeping an open WS connection.
So that's 8KB (will be higher with more usage) for TCP buffers in the kernel, 4KB or so for cowboy, and 28KB or so left for various other bits of the system when amortized per connection.
Still, I wonder how low could one get when implementing this at a much lower level. 41kB per connection seems like a lot of bookkeeping for something that's essentially a handle to a socket? Yes there's a process overhead in BEAM, but based on the Erlang docs, this should be only 309 memory words.