▲ | klabb3 2 days ago | |||||||
> Their explanation for why Go performs badly didn't make any sense to me. To me, the whole paper is full of misunderstanding, at least the analysis. There's just speculation based on caricatures of the language, like "node is async", "c++ is low level" etc. The fact that their C++ impl using uWebSocket was significantly slower than then Node, which used uWebSocket bindings, should have led them to question the test setup (they probably used threads which defeats the purpose of uWebSocket. Anyway.. The "connection time" is just HTTP handshake. It could be included as a side note. What's important in WS deployments are: - Unique message throughput (the only thing measured afaik). - Broadcast/"multicast" throughput, i.e. say you have 1k subscribers you wanna send the same message. - Idle memory usage (for say chat apps that have low traffic - how many peers can a node maintain) To me, the champion is uWebSocket. That's the entire reason why "Node" wins - those language bindings were written by the same genius who wrote that lib. Note that uWebSocket doesn't have TLS support, so whatever reverse proxy you put in front is gonna dominate usage because all of them have higher overheads, even nginx. Interesting to note is that uWebSocket perf (especially memory footprint) can't be achieved even in Go, because of the goroutine overhead (there's no way in Go to read/write from multiple sockets from a single goroutine, so you have to spend 2 gorountines for realtime r/w). It could probably be achieved with Tokio though. | ||||||||
▲ | Svenskunganka 2 days ago | parent | next [-] | |||||||
The whole paper is not only full of misunderstandings, it is full of errors and contradictions with the implementations. - Rust is run in debug mode, by omitting the --release flag. This is a very basic mistake. - Some implementations is logging to stdout on each message, which will lead to a lot of noise not only due to the overhead of doing so, but also due to lock contention for multi-threaded benchmarks. - It states that the Go implementation is blocking and single-threaded, while it in fact is non-blocking and multi-threaded (concurrent). - It implies the Rust implementation is not multi-threaded, while it in fact is because the implementation spawns a thread per connection. On that note, why not use an async websocket library for Rust instead? They're used much more. - Gives VM-based languages zero time to warm up, giving them very little chance to do one of their jobs; runtime optimizations. - It is not benchmarking websocket implementations specifically, it is benchmarking websocket implementations, JSON serialization and stdout logging all at once. This adds so much noise to the result that the result should be considered entirely invalid. > To me, the champion is uWebSocket. That's the entire reason why "Node" wins [...] A big part of why Node wins is because its implementation is not logging to stdout on each message like the other implementations do. Add a console.log in there and its performance tanks. | ||||||||
▲ | austin-cheney 2 days ago | parent | prev [-] | |||||||
There is no HTTP handshake in RFC6455. A client sends a text with a pseudo unique key. The server sends a text with a key transform back to the client. The client then opens a socket to the server. The distinction is important because assuming HTTP implies WebSockets is a channel riding over an HTTP server. Neither the client or server cares if you provide any support for HTTP so long as the connection is achieved. This is easily provable. It also seems you misunderstand the relationship between WebSockets and TLS. TLS is TCP layer 4 while WebSockets is TCP layers 5 and 6. As such WebSockets work the same way regardless of TLS but TLS does provide an extra step of message fragmentation. There is a difference in interpreting how a thing works and building a thing that does work. | ||||||||
|