Live data from Hacker News

Websocketd

websocketd.com

201–210 of 233 posts

Re: Websocketd

#201
post #125

Earlier quoted context omitted.

8ms per fork means you can only accept 125 connections per second. (per core) That means it's only viable for connections where the connection is very long lived and messages are very sparse (because context switches).

I find it ironic that people will complain about milliseconds for a fork and talk about the time for context switches... and then serve their pages using an interpreted language that is an order of magnitude slower than it could be in a compiled language...

Who did that? I saw no one talking about interpreted languages here.

Re: Websocketd

#202
post #107

Earlier quoted context omitted.

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…

Completely true, but in a realistic small workload situation with a 0.5ms response time the pthread context switch is already only 2usec or 0.4% of the total time. Goroutines can be infinitely faster and not be able to meaningfully improve overall performance. This is why thread per request servers like jlhttp are right up there with fasthttp etc in terms of total throughput. https://www.techempower.com/benchmarks/#s…

Something notable is that jlhttp and fasthttp are both using worker pools. fasthttp uses worker pools of goroutines, and jlhttp uses traditional thread pooling.

Thread pooling is an effective solution to improve webserver performance, and it generally works well. In these synthetic benchmarks, you can't even really see much of a downside. In reality a lot of these benchmarks are only so good because they have requests that complete very quickly, and I think if you add a random sleep() into them many of them will just die outright because they can't handle that much concurrency and block waiting for free workers. You might think that is unrealistic, but consider that many people have Go servers that are making RPCs all over the place, and an actual large amount of time can just be spent waiting on other RPCs. It's a real thing!

And if the world were just responding to HTTP requests, obviously something like Goroutines would be overkill. But, one of my favorite uses of Goroutines was implementing a messaging server where each consumer, queue, exchange were all their own Goroutines. I was inspired by RabbitMQ for the design but unfortunately could not use it in this use case. Luckily Goroutines worked really great here and I was able to scale this thing up hugely. To me this is where they're really great: they're super flexible. They work pretty well for short-lived HTTP requests, but also great for entirely different and more complicated use cases.

Looking back at the benchmark, one of the more interesting approaches here is go-prefork[1], which works by spawning n/2 executables with 2 threads each. I can only imagine the optimal amount of threads was complicated to determine and maybe even has something to do with hyperthreading. Of course the advantage here is the reduced amount of shared state that leads to less contention, and it does indeed show up on the benchmark. In this setup, it looks weird because there's no load balancer (could be something as simple as some iptables rules) or anything in front. In practice, this would be much akin to running separate instances on the same box, which is also a reasonable approach, and I used this approach myself when scheduling servers. Oddly, I don't think they tried the same approach for fasthttp.

I think what else the benchmark shows is how clever you don't have to be in Go to get good performance. go-postgres is routinely in the middle of the pack and it is literally just using the standard library and goroutines in the most basic fashion. It's effectively not optimized. And in reality, in many cases with more complex servers, the overhead is low enough that it isn't worth your time to optimize it much more.

[1]: https://github.com/TechEmpower/FrameworkBenchmarks/blob/mast...

Re: Websocketd

#203
post #182
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.

I would really like to see a benchmark for: stand alone fork in small statically compiled binary and also every combination of: [[vfork, fork] + exec, posix_spawn] + [small static binary, small dynamic binary]. I understand that for big interpreted languages like Python it's certainly slow, but with advent of Rust I would believe that CGI could make a come back. It's fast enough for many tasks and it gives great isol…

A long time ago I used to write CGI endpoints in C (strangely, not because I had to, I just wasn't as good at perl ). I used to say "its not a CGI 'script' maaan! I wrote it in C" with the accompanying l33t glance of respect in response ;)

Anyhoo - same arguments about forking, process & memory limits arose ; so things like FastCGI and ISAPI were the solution to reduce/avoid some of those overheads.

I suspect Rust based CGI endpoints would have similar issues.

But I've been thinking about this CGI comeback from time to time - the left side of backend infrastructure (load balancerss, reverse proxies etc) and middle tier machine resources are much better now. Docker containers and lambda spin up is similar to some degree in terms of topology but maybe with even more overhead?

..so does does make one wonder if cgi like simplicity make a comeback with today's order of magnitude better infrastructure? I keep waiting for someone to come up with "lambdaGI" ..with will lead to "fastLambdaGI" and so on (and that's not a snarky comment).

Re: Websocketd

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

Sometimes you know your scale. Say you have a website for your local area D&D club. You know that nobody outside a 20 mile radius is going to ever really bother looking at your stuff. And you know that there are about 200 people interested in D&D in this area. You need a contact form on your site to email you when someone has a question. How many connections at most would you realistically expect to have to process in this case per second/year/decade?

Re: Websocketd

#205
post #188

Earlier quoted context omitted.

Usually you notice issues by the server locking up, the clients reporting problems, or messages being missing from the log (which you tend to notice when you search for specific things in the logs).

So how do you know that you're not just getting 80% of "log entry X" just because you get hits for them every now and then?

Logging is usually pretty deterministic.

A request might generate log entries a, b1, c or a, b2, c, depending on some conditions. The exact contents vary by request (otherwise there would be no need to log them), but the type is always the same.

If you find logs for c without either b1/b2 or a, you know log entries went missing.

If you have a 20% miss rate with recording your log entries, and you analyze just 20 log entries, the chance that one of them is missing is already around 98.8%.

If you actually use your logs for anything, it becomes pretty obvious pretty quickly when they are incomplete.

Re: Websocketd

#206

> Each inbound WebSocket connection runs your program in a dedicated process. Connections are isolated by process. I see you and 10,900 other "software developers" get the point of WebSocket. It's especially "impressive" when you written the whole thing in Go and could have used goroutines and channels, which could easily handle hundreds of thousand of connections (maybe millions). Terrible design! For a long time I…

I've never felt a stronger sense of https://xkcd.com/386/ in my life. Why are you being so cynical? The author made a tool with no interface that turns any program into a websocket server, making no claim that it can directly replace production servers focused on scale. What are you complaining about? Who hurt you?

Re: Websocketd

#207

Earlier quoted context omitted.

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…

Sometimes you know your scale. Say you have a website for your local area D&D club. You know that nobody outside a 20 mile radius is going to ever really bother looking at your stuff. And you know that there are about 200 people interested in D&D in this area. You need a contact form on your site to email you when someone has a question. How many connections at most would you realistically expect to have to process i…

More than you’d assume, once you factor in search engine crawlers, miscellaneous bots and automated tools that bad actors run to probe websites looking for vulnerabilities. However if still expect CGI to stand up against that.

Performance arguments aside and given the type of site you describe, wouldn’t it be more convenient for the developer to use Wordpress or one of those website builder as a service things instead of inventing something from scratch in CGI?

I get the argument that some personal sites wouldn’t get much traffic but the argument that CGI is easier to build than any non-CGI alternative simply isn’t true any more and hasn’t been the case for more than a decade.

I know I’m coming across as passionately against CGI and I assure you that isn’t the case (I recently chose to use CGI as a private API endpoint for some Alexia skills I’d written for myself). But for a public site there isn’t really a strong argument in favour of CGI anymore given the wealth of options we have available.

Re: Websocketd

#209

Earlier quoted context omitted.

Sometimes you know your scale. Say you have a website for your local area D&D club. You know that nobody outside a 20 mile radius is going to ever really bother looking at your stuff. And you know that there are about 200 people interested in D&D in this area. You need a contact form on your site to email you when someone has a question. How many connections at most would you realistically expect to have to process i…

More than you’d assume, once you factor in search engine crawlers, miscellaneous bots and automated tools that bad actors run to probe websites looking for vulnerabilities. However if still expect CGI to stand up against that. Performance arguments aside and given the type of site you describe, wouldn’t it be more convenient for the developer to use Wordpress or one of those website builder as a service things instea…

Point taken on the bots but the static part shouldn’t go through the CGI anyways.

The irony of decrying poor performance yet suggesting WordPress is pretty priceless :)

I agree that most people would be better served with Squarespace/Wix but I run into the situation or static site + 1-2 bits of dynamic form processing frequently enough to warrant having a simple solution for it. When the site doesn’t warrant spending money on, sometimes a shared host + CGI is just right. But I think this is for some very rare cases. Most people should outsource these types of headaches.

Re: Websocketd

#210
post #153
post #125

Earlier quoted context omitted.

8ms per fork means you can only accept 125 connections per second. (per core) That means it's only viable for connections where the connection is very long lived and messages are very sparse (because context switches).

If you use websocket for short lived connections, you are doing something wrong. -- Meta observation: Maybe this is the bane of smartphone era and small screens, but the context of the discussion seems to disappear instantly. Subject: websockets > forking processes > .. aaand the websocket context is lost and we are talking generally about forks in web applications with growing thread.

> If you use websocket for short lived connections, you are doing something wrong.

Pretty-much true, but I remember a funny story from Dropbox where their websocket service couldn't come back up after a crash because their normal users trying to re-open super long lived connections all at once was well-beyond the capacity of the system

Post reply on HN