Live data from Hacker News

Websocketd

websocketd.com

71–80 of 233 posts

Re: Websocketd

#71
post #26

This is the second or third "it's CGI again" thing I've seen in the past year. While these things are cool and definitely have their place, it's still worth noting that process per connection scales fairly poorly, simply because processes and forking are relatively expensive, and therefore it's probably unwise to deploy something like this in production anymore. It is what it is, I suppose.

> processes and forking are relatively expensive

This and "async is always faster" are two things which are no longer true on modern hardware.

Forking a process on Linux uses the same clone() syscall as creating a thread so forking a small binary takes only tens of microseconds, leaving plenty of time for https://eli.thegreenplace.net/2018/launching-linux-threads-a...

Re: Websocketd

#72
post #68
post #58

Earlier quoted context omitted.

Of course any UNIX-like worth its salt is going to support Copy on Write and whatnot. But even then, forking is still quite slow relative to not doing anything at all. Here's my point of view: 1. Forking is first and foremost a system call. (To be fair, I realize even memory allocation is much of the time, but still.) The kernel is going to do a bunch of work (as fast as it can, of course) and you're going to end up…

They tried green threads years and years ago in Java and then reversed course, and M:N was also a thing on NetBSD years ago. I wonder why Go is working where the others went away from it?

I am pretty sure Java's historical use of green threads was an issue of portability and not performance. They used traditional threading primitives. Java's decision to use green threads may have actually made a lot of sense in an era when consumer computers typically only had one physical thread to begin with.

Go on the other hand is based on CSP principles and a threading model that looks like actors. The threading model is deeply ingrained in the language, and it is designed around it. Goroutines are very cheap in Go, and the scheduler is fairly effective because it knows what threads to wake when - it's not blind. Goroutines are scheduled across n threads, not just a single OS thread, so they can take good advantage of multicore or multi CPU systems. This design does hurt C interoperability a bit, but imo it's greatly worth it.

Go is not the only language that works this way. I believe its concurrency model was inspired a lot by Erlang with its 'processes' model.

Re: Websocketd

#73
post #68
post #58

Earlier quoted context omitted.

Of course any UNIX-like worth its salt is going to support Copy on Write and whatnot. But even then, forking is still quite slow relative to not doing anything at all. Here's my point of view: 1. Forking is first and foremost a system call. (To be fair, I realize even memory allocation is much of the time, but still.) The kernel is going to do a bunch of work (as fast as it can, of course) and you're going to end up…

They tried green threads years and years ago in Java and then reversed course, and M:N was also a thing on NetBSD years ago. I wonder why Go is working where the others went away from it?

From what I recall, Java didn't switch because it didn't work. I think it switched because the green threads were built on what Solaris supported, and they moved to full OS threading to support Windows, Linux, Mac etc.

Re: Websocketd

#74
post #26

This is the second or third "it's CGI again" thing I've seen in the past year. While these things are cool and definitely have their place, it's still worth noting that process per connection scales fairly poorly, simply because processes and forking are relatively expensive, and therefore it's probably unwise to deploy something like this in production anymore. It is what it is, I suppose.

> processes and forking are relatively expensive This and "async is always faster" are two things which are no longer true on modern hardware. Forking a process on Linux uses the same clone() syscall as creating a thread so forking a small binary takes only tens of microseconds, leaving plenty of time for https://eli.thegreenplace.net/2018/launching-linux-threads-a...

For sure, but the biggest overhead is usually application startup (in say Java, Dart, Node, Python, etc) where just the VM can take a few 100ms to start. Using a compiled language would most likely be the way to go for maximum performance (although it's less important if the WebSocket is long lasting)

Re: Websocketd

#75
post #26

This is the second or third "it's CGI again" thing I've seen in the past year. While these things are cool and definitely have their place, it's still worth noting that process per connection scales fairly poorly, simply because processes and forking are relatively expensive, and therefore it's probably unwise to deploy something like this in production anymore. It is what it is, I suppose.

> processes and forking are relatively expensive This and "async is always faster" are two things which are no longer true on modern hardware. Forking a process on Linux uses the same clone() syscall as creating a thread so forking a small binary takes only tens of microseconds, leaving plenty of time for https://eli.thegreenplace.net/2018/launching-linux-threads-a...

Sure. Under Linux, processes and threads are both just tasks anyways. Processes may be nearly as efficient as threads, but you can do one better by not even having to spawn new threads per worker, which is what a concurrency model like Go's or Erlang's enable with ease. CGI and Websocketd also have significantly more costs than just a fork since they need to execute a target program.

And even forgetting the costs of forking, threads are not necessarily much better anyways. I can easily have a single Go program scheduling literally hundreds of thousands of Goroutines across just a few OS level threads and have no problems whatsoever, and in fact I've done exactly that in production, whereas I would never even dream of doing that with threads.

Node.JS's event loop model also doesn't need to spawn threads per connections.

When I say processes and forking are relatively expensive, I don't mean compared to doing the exact same thing with threads; I mean compared to more modern alternatives, like using an event loop or Goroutines.

Re: Websocketd

#76
post #26

This is the second or third "it's CGI again" thing I've seen in the past year. While these things are cool and definitely have their place, it's still worth noting that process per connection scales fairly poorly, simply because processes and forking are relatively expensive, and therefore it's probably unwise to deploy something like this in production anymore. It is what it is, I suppose.

Depends on what your needs are. In many cases, you need to scale to a few dozen connections per day, and simplicity is far more valuable than performance. If you're pushing the limits of performance, any off the shelf solution is probably not going to scale as well as it could for your specific workload.

Re: Websocketd

#77
post #54
post #35

Earlier quoted context omitted.

But websocket connections are usually long lasting. So the cost of the fork is less important.

It probably scales better than a forking HTTP server, but probably not much; modern HTTP connections tend to be at least a little bit long lasting and few people would dare serve a large site on a forking webserver (in part thanks to the fact that most webservers have moved on to workers or event loops.) It certainly would hold up inordinately poor to a DDoS attack.

A process per client with keepalive is definitely a losing proposition. But if you're willing to run old-school one request per connection, it's not unreasonable (although adding TLS to that is). Many years ago, while I was at Yahoo, someone made a clever hack: have a daemon that holds keepalive sockets and passes them to the (y)Apache daemon when they have something to read -- when Apache is done with the request, give it back to the daemon. (Sockets passed back and forth as file descriptors on a Unix socket). A further many years ago, David Filo came up with the idea of accept filters -- allowing a program to request the kernel to accept connections and have accept only return sockets that have a fully formed http request already, so an Apache (or whatever crazy webserver before Yahoo switched to Apache) wouldn't have to wait for the client there either.

Re: Websocketd

#80
post #26

This is the second or third "it's CGI again" thing I've seen in the past year. While these things are cool and definitely have their place, it's still worth noting that process per connection scales fairly poorly, simply because processes and forking are relatively expensive, and therefore it's probably unwise to deploy something like this in production anymore. It is what it is, I suppose.

[deleted]
Post reply on HN