Live data from Hacker News

Websocketd

websocketd.com

101–110 of 233 posts

Re: Websocketd

#101
post #86

Earlier quoted context omitted.

> 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 an…

> I have extreme doubts that threads beat goroutines

Why? Goroutines use the same syscall heavy non-blocking IO as event loops, just with coroutines for programmer convenience.

The biggest difference between Goroutines and pthreads is that Goroutines only have a 2kb default stack size and pthreads have a 2MB stack.

In high thread concurrency situations it's common to turn the pthread stack size down to 48 or 64kb to allow running tens or hundreds of thousands of OS threads. There's even a JVM config flag for it.

Re: Websocketd

#102
The unix philosophy is massively overrated because processes are unwieldy in practice, and support only weak notions of composition even in theory.

Re: Websocketd

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

Is unix defined as having small binaries? I don't think that's true. Yes, it's statically linked and as a result somewhat large. This is a program built around executing programs and communicating over pipes. It's composing programs together. I think that's certainly UNIX-ish.

> Is unix defined as having small binaries? I don't think that's true. Yes, it's statically linked and as a result somewhat large.

No, but literally the first point is:

> Make each program do one thing well. To do a new job, build afresh rather than complicate old programs by adding new features.

It's not hard to see how this would apply to libraries, and how including third party code in your binary would break this idea because you're essentially "freezing" the application in time.

Your definition regarding "composing programs together" is not all that makes a program UNIX-ish.

Re: Websocketd

#104
post #99
post #35

Earlier quoted context omitted.

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

Socket connection alone is too expensive. IRC shows us that maintaining a reliable socket for most folks is next to impossible.

On the contrary. IRC shows that maintaining a consistent network where every part can always reach every other part is tricky, but the most common problem with irc networks is not clients getting booted off, but net-splits that usually automatically resolves pretty quickly.

That they're visible to clients is an issue with how channels spans servers and how operator status and channel membership is tied to who happens to be on a channel on a specific partition at a certain time, and how messages are propagated when splits resolve, and how inter-server communications happens.

So it has plenty of lessons if you want to build a chat network, but nothing with it suggests maintaining a connection is otherwise a big problem.

In general what it boils down to is the word "reliable": You would want to write your app so that a client that disconnects and reconnects gets a sensible behavior on reconnecting, e.g. by queuing messages when it makes sense, and discard them if it does not, to paper over temporary connection failures.

But you would need to do that if you were to use stateless request/response pairs anyway.

Re: Websocketd

#105
post #75

Earlier quoted context omitted.

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

I never wrote that going back to CGI and creating a process or thread per request was a good idea, only that forking is much cheaper than often thought.

Event loops and userland cooperative multitasking like Goroutines predate Linux 2.6 kernel threads. They're not "more modern".

Re: Websocketd

#106
post #63

Earlier quoted context omitted.

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?

Friendly reminder that not everyone is in a position where they can create pull requests against random projects: they might not have time, or clearance from their company's legal department, or…

Re: Websocketd

#107
post #86

Earlier quoted context omitted.

>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 an…

> I have extreme doubts that threads beat goroutines Why? Goroutines use the same syscall heavy non-blocking IO as event loops, just with coroutines for programmer convenience. The biggest difference between Goroutines and pthreads is that Goroutines only have a 2kb default stack size and pthreads have a 2MB stack. In high thread concurrency situations it's common to turn the pthread stack size down to 48 or 64kb to…

1, because the Goroutine context switch is Insanely cheap. There's no preempting, the scheduler runs on function calls and the context switches are very cheap - just swapping a few registers I believe. This means a single thread could blow through an enormous amount of goroutines in no time. I know, kernel mode switches are fast, we optimize this all the time, but doing nothing in place of doing something will always be inordinately cheaper.

2, because the Go scheduler has awareness about the state of the goroutines that an OS scheduler would not, so it can make more intelligent decisions about what goroutines to wake up and when.

You can really have pretty much as many goroutines as you want. Hundreds of thousands of OS threads lands you firmly into tweaking kernel settings land. My local thread max on my desktop is just 127009 - that wouldn't fly for a huge machine running many Go apps, which is exactly the kind of circumstance I was in (using Kubernetes, to be exact.)

Re: Websocketd

#108
post #95
post #76

Earlier quoted context omitted.

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.

Yes! Every mention of CGI also gets a sneer and a reminder of how poorly it scales, but nothing I do requires scale in that sense. "In production" doesn't always mean "hundreds of requests per second." Every road doesn't need 8 lanes.

I’ve had developers say this before when building public websites and it has cost us in lost revenue when the site has gone offline or cost us lots in virtual hardware having to scale the number of servers available to meet higher than expected volumes of traffic.

Don’t get me wrong, I'm not suggesting that everyone should be building their site like it’s Facebook or Google, but when every public website is already sat on a proverbial motorway, it can be dangerously shortsighted to build your site to only meet demand with no room to scale. CGI falls under that category. There are plenty of platforms that are still very easy to build and deploy, developer friendly, and still runs circles around the performance of CGI.

(Please note that I am talking about public sites specifically and not intranets or other IP white listed resources)

Re: Websocketd

#109
post #56

Earlier quoted context omitted.

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.

I don't understand why the daemon needs to client to escape newlines in the message. Can't it handle that before feeding the message to STDIN?

For example, my browser sends:

    This is line one...
    ...and this is line two
as a string ("This is line one...\n...and this is line two") and the websocketd receives that, and passes along

    This is line one...\\n...andthis is line two\n
to the STDIN.

It knows that the message is one thing, so the newlines aren't the same as the end of message, right?

It'd also be nice to use EOF as the indicator to flush STDOUT to the client, so the program can also emit newlines without needing to escape them first.

All that being said, this is nifty. I think I can use this for some low-volume ideas I have on an internal app. The newline handling isn't a problem because I'm not replacing anything that already exists.

Re: Websocketd

#110
post #95

Earlier quoted context omitted.

Yes! Every mention of CGI also gets a sneer and a reminder of how poorly it scales, but nothing I do requires scale in that sense. "In production" doesn't always mean "hundreds of requests per second." Every road doesn't need 8 lanes.

I’ve had developers say this before when building public websites and it has cost us in lost revenue when the site has gone offline or cost us lots in virtual hardware having to scale the number of servers available to meet higher than expected volumes of traffic. Don’t get me wrong, I'm not suggesting that everyone should be building their site like it’s Facebook or Google, but when every public website is already s…

Used in production doesn't always mean used by all users of a public app that might go viral.

If you have an app with an admin interface/CMS/monitoring interface and you know there won't be 50 administrators for your app before the end of the year this works great (assuming you can reverse proxy this to add auth or something).

Post reply on HN