Live data from Hacker News

Websocketd

websocketd.com

81–90 of 233 posts

Re: Websocketd

#81
post #35
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.

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

It's not so much the fork but the memory cost. Each of those subprocesses has at least one call stack = 2 megabytes of memory. 2 megabytes per connection is many many orders of magnitude more that you would use in an asynchronous server.

Re: Websocketd

#82
post #58

Earlier quoted context omitted.

Not that much on modern Linux/BSD systems at least. The kernel is smart enough to just copy fewer pages when forking not the entire parent process image.

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…

> 2. For hundreds of tasks, it becomes less effective. Threads will rapidly go in and out of I/O wait and the scheduler has to balance all of this.

Surprisingly, even thousands of threads can often have better throughput than using event loops and non-blocking IO: https://www.slideshare.net/e456/tyma-paulmultithreaded1

> The cost of OS-level context switching is non-trivial

On modern hardware it's non-zero but trivial: https://eli.thegreenplace.net/2018/measuring-context-switchi...

Re: Websocketd

#83

How do posts like this end up at #2 on the front page with just one comment? Websocketd doesn't strike me as an particularly popular or well known tool.

Well if it was popular or well known why would it be news-worthy?

Indeed. Discovering interesting new things is one of the main purposes of HN.

Re: Websocketd

#84
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 wonder why Go is working where the others went away from it?

Quite frankly, because Go developers don't learn from other's mistakes and reinvent square wheels.

Kernel threads will always be better and faster than usermode threads.

This is because any inefficiency in threading comes from the scheduler. Your usermode scheduler will always necessarily be slower and worse; it just makes so much sense to put your scheduling code where your context switching and process isolation code already is.

Sure, you can get a short-term gain by iterating fast and testing code if kernel developers are too slow and/or unwilling; but then eventually your code will get merged into the kernel anyways once you're done. So really usermode threads are only good as a rapid prototyping tool, not something for serious use.

Re: Websocketd

#86
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…

> 2. For hundreds of tasks, it becomes less effective. Threads will rapidly go in and out of I/O wait and the scheduler has to balance all of this. Surprisingly, even thousands of threads can often have better throughput than using event loops and non-blocking IO: https://www.slideshare.net/e456/tyma-paulmultithreaded1 > The cost of OS-level context switching is non-trivial On modern hardware it's non-zero but trivia…

>Surprisingly, even thousands of threads can often have better throughput than using event loops and non-blocking IO

Hundreds may be a bad example, it's going to vary based on how big your server is but there is a tipping point where threads become very infeasible. I've yet to hit that limit with Goroutines and have literally hit millions of them on relatively small allocations without much of a hitch. Event loops and non blocking IO may perform worse than threads, but I have extreme doubts that threads beat goroutines (and equivalent models like erlang processes.)

Re: Websocketd

#88
post #63

It looked simple enough, but I was curious about the threading example on https://github.com/joewalnes/websocketd/wiki/CPP-Input-Outpu... The variable `count` appears to be incremented non-atomically from two different threads. Is that safe in C++?

It is unsafe. But it would be safe if these two lines were swapped: count++; pthread_mutex_lock(&m); since the reader already holds the mutex while reading `count`.

Do a PR or equivalent?

Re: Websocketd

#89
post #68

Earlier quoted context omitted.

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 wonder why Go is working where the others went away from it? Quite frankly, because Go developers don't learn from other's mistakes and reinvent square wheels. Kernel threads will always be better and faster than usermode threads. This is because any inefficiency in threading comes from the scheduler. Your usermode scheduler will always necessarily be slower and worse; it just makes so much sense to put your sche…

>Quite frankly, because Go developers don't learn from other's mistakes and reinvent square wheels.

Your response doesn't even start on the right foot, since Java never used green threads for performance and therefore is not a good place to hedge this argument at. Citation needed if you're going to start with that.

You can also go ahead and insult the Erlang developers for Processes since they did it first:

http://erlang.org/doc/reference_manual/processes.html

>This is because any inefficiency in threading comes from the scheduler. Your usermode scheduler will always necessarily be slower and worse; it just makes so much sense to put your scheduling code where your context switching and process isolation code already is.

You know, a Go context switch doesn't hit the kernel. It's not more expensive than a kernel context switch. I don't know why you'd think it is. Why not inline scheduling to the process where it knows what's blocked on what?

>Sure, you can get a short-term gain by iterating fast and testing code if kernel developers are too slow and/or unwilling; but then eventually your code will get merged into the kernel anyways once you're done. So really usermode threads are only good as a rapid prototyping tool, not something for serious use.

You can hold your breath for threads to become cheaper than goroutines, but careful not to suffocate. A goroutine pretty much just needs a stack, 4kb. The kernel thread has structures, well, in the kernel, for paging, for the task itself, and the stack structure is bigger (think you can at least adjust that though.)

And as for integrating the Go GC into the scheduler... I'd love to see what Linus's thoughts on merging that to kernel are!

Doesn't matter if you just have a few thousand threads but that's a limiting way to look at something. RabbitMQ can have processes all over the place for everything and have more processes than you could ever have threads and it remains among best in class for performance.

Post reply on HN