Live data from Hacker News

Websocketd

websocketd.com

61–70 of 233 posts

Re: Websocketd

#61

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.

Re: Websocketd

#62
post #32

Earlier quoted context omitted.

Is that a feature or a bug of *nix?

Not really; IIRC forking is more expensive on NT, and *nix processes/threads tend to be fairly cheap. It might be a generally expensive model, and threads/pools are probably the better-scaling option regardless of OS.

On NT though, there's a deeper divide between processes and threads. Threads on NT should be a lot cheaper. Especially since you can't fork on NT without diving into undocumented APIs* :)

*On the Windows subsystem, of course. There's the lower level ZwCreateProcess function which can/could be used to fork, but it's undocumented and I believe it only existed for the old SfU. Now that that's gone and Linux Subsystem uses something called Pico Processes, I'm guessing this old fork flag is pretty much unsafe to use for anything at all.

Re: Websocketd

#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`.

Re: Websocketd

#64
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.

> modern HTTP connections tend to be at least a little bit long lasting

But CGI doesn't fork per TCP connection; it forks per HTTP request/response.

Re: Websocketd

#65

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.

Then you run a GC and dirty all your pages.

Yeah; forking is cheaper for low memory programs with no moving GC.

Re: Websocketd

#66
post #56

Doesn’t this have an impedance mismatch? Stdin/out are stream based. Websocket is message based. There is no guarantee you can transmit the content of a single WebSocket message inside a single os read or write call. Unless you expect that on both sides messages might be fragmented across multiple calls and callbacks. But I don’t see the docs mentioning that.

Newlines. Each line written to STDOUT is sent as one frame, and each frame received is read from STDIN followed by a synthetic newline. The FAQ explains how to escape multiline messages (or binary data, presumably). https://github.com/joewalnes/websocketd/wiki/FAQ#how-can-i-s...

Ah thanks that makes sense. I didn't see it when I glimpsed over the site.

That should provides reliable framing on both sides. But as shown in the linked it page it also comes with the downside of not being able to send raw websocket messages which contain a new line - so it's not possible to port existing applications from other websocket servers to this one without having to change communication.

Re: Websocketd

#67

Doesn’t this have an impedance mismatch? Stdin/out are stream based. Websocket is message based. There is no guarantee you can transmit the content of a single WebSocket message inside a single os read or write call. Unless you expect that on both sides messages might be fragmented across multiple calls and callbacks. But I don’t see the docs mentioning that.

Interested to know in what situations you anticipate this would cause problems?

I estimated that the daemon just tried to send the data from the local application as a websocket messages whenever it received something through the FD. If the application tries to write a 100kB message to stdout, the daemon might pull this out in smaller chunks of it's socket, since the OS buffer might be not as big. If it's 50kB, then the daemon would send 2 50kB messages instead of a single 100kB one. If the JS on the other side would have estimated that everything is inside a single message things would be broken.

However it looks like the Daemon might wait for a newline until it forwards everything as a message. Which at least fixes this problem, but might have other side effects.

Re: Websocketd

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

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?

Re: Websocketd

#69
post #10

Ok I know the software-today-is-so-bloated trope is overplayed but... "the UNIX way"? The compiled Linux x86_64 binary is 7 megabytes. All of System V combined was not that big.

It's kind of just the way golang's compiler statically compiles everything. If you use gccgo, you can get a 762KiB binary easily.

Re: Websocketd

#70
post #54

Earlier quoted context omitted.

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.

> modern HTTP connections tend to be at least a little bit long lasting But CGI doesn't fork per TCP connection; it forks per HTTP request/response.

True, but as far as I know none of the major HTTP servers use forking anymore either. I believe there was a time when forking per connection was fairly standard for servers.
Post reply on HN