Live data from Hacker News

Serving a half billion requests per day with Rust and CGI

jacob.gold

51–60 of 118 posts

Re: Serving a half billion requests per day with Rust and CGI

#51
Currently in Europe. Earlier, was trying to use the onboard wifi on a train, which has frequent latency spikes as you can imagine. It never quite drops out, but latency does vary between 50ms-5000ms on most things.

I struggled for _15 mins_ on yet another f#@%ng-Javascript-based-ui-that-does-not-need-to-be-f#@%ng-Javascript, simply trying to reset my password for Venmo.

Why... oh why... do we have to have 9.1megabytes of f#@*%ng scripts just to reset a single damn password? This could be literally 1kb of HTML5 and maybe 100kb of CSS?

Anyway, this was a long way of saying I welcome FastCGI and server side rendering. Js need to be put back into the toys bin... er trash bin, where it belongs.

Re: Serving a half billion requests per day with Rust and CGI

#52

How meaningful is “per day” as a performance metric?

As a comparison between implementations it can be useful. It is more than a big enough number that, if the test was actually done over a day, temporary oddities are dwarfed. If the test was done over an hour and multiplied then it is meaningless: just quote the per hour figure. Same, but more so, if the tests were much shorter than an hour.

Re: Serving a half billion requests per day with Rust and CGI

#53
post #8

Honestly, I'm just trying to understand why people want to return to CGI. It's cool that you can fork+exec 5000 times per second, but if you don't have to, isn't that significantly better? Plus, with FastCGI, it's trivial to have separate privileges for the application server and the webserver. The CGI model may still work fine, but it is an outdated execution model that we left behind for more than one reason, not j…

Serverless is a marketing term for CGI, and you can observe that serverless is very popular.

A couple of years ago my (now) wife and I wrote a single-event Evite clone for our wedding invitations, using Django and SQLite. We used FastCGI to hook it up to the nginx on the server. When we pushed changes, we had to not just run the migrations (if any) but also remember to restart the FastCGI server, or we would waste time debugging why the problem we'd just fixed wasn't fixed. I forget what was supposed to start the FastCGI process, but it's not running now. I wish we'd used CGI, because it's not working right now, so I can't go back and check the wedding invitations until I can relogin to the server. I know that password is around here somewhere...

A VPS would barely have simplified any of these problems, and would have added other things to worry about keeping patched. Our wedding invitation RSVP did need its own database, but it didn't need its own IPv4 address or its own installation of Alpine Linux.

It probably handled less than 1000 total requests over the months that we were using it, so, no, it was not significantly better to not fork+exec for each page load.

You say "outdated", I say "boring". Boring is good. There's no need to make things more complicated and fragile than they need to be, certainly not in order to save 500 milliseconds of CPU time over months.

Re: Serving a half billion requests per day with Rust and CGI

#55
post #36

Earlier quoted context omitted.

Absolutely, I'm not recommending for everybody to go back using CGI (the protocol). I was responding to this: > The CGI model may still work fine, but it is an outdated execution model The CGI model of one process per request is excellent for modern hardware and really should not be scoffed at anymore IMO. It can both utilize big machines, scale to zero, is almost leak-proof as the OS cleans up all used memory and fi…

The part of the execution model that is dated is this: > having the web server execute stuff in a specific folder inside the document root just seems like a recipe for problems

Typically I've run cgi from a directory outside the document root. That's easy, and I think was the defaults?

That said, fork+exec isn't the best for throughput. Especially if the httpd doesn't isolate forking into a separate, barebones, child process, fork+exec involves a lot of kernel work.

FastCGI or some other method to avoid forking for each request is valuable regardless of runtime. If you have a runtime with high startup costs, even more so.

Re: Serving a half billion requests per day with Rust and CGI

#56
post #36

Earlier quoted context omitted.

Absolutely, I'm not recommending for everybody to go back using CGI (the protocol). I was responding to this: > The CGI model may still work fine, but it is an outdated execution model The CGI model of one process per request is excellent for modern hardware and really should not be scoffed at anymore IMO. It can both utilize big machines, scale to zero, is almost leak-proof as the OS cleans up all used memory and fi…

The part of the execution model that is dated is this: > having the web server execute stuff in a specific folder inside the document root just seems like a recipe for problems

What kind of problems? Like, if the administrator put something inside that directory (Unix doesn't have folders) that the web server shouldn't execute? That kind of problems? I've literally never had that problem in my life and I've had web pages for 30 years.

Re: Serving a half billion requests per day with Rust and CGI

#58
post #31

It'd be interesting to compare the performance of the author's approach to an analogous design that changes CGI for WASI, and scripts/binaries to Wasm.

Would it? It would be exactly the same but a bit slower because of the WASM overhead.

No, Linux typically takes about 1ms to fork/exit/wait and another fraction of a millisecond to exec, and was only getting about 140 requests per second per core in this configuration, while creating a new WASM context is closer to 0.1ms. I suspect the bottleneck is either the web server or the database, not the CGI processes.

Re: Serving a half billion requests per day with Rust and CGI

#59
post #17

I’m interested why Rust and C have similarly bad tail latencies but Go doesn’t.

sqlite resolves lock contention between processes with exponential backoff. When the WAL reaches 4MB it stops all writes while it gets compacted into the database. Once the compaction is over all the waiting processes probably have retry intervals in the hundred millisecond range, and as they exit they are immediately replaced with new processes with shorter initial retry intervals. I don't know enough queuing theory to state this nicely or prove it, but I imagine the tail latency for the existing processes goes up quickly as the throughput of new processes approaches the limit of the database.

Re: Serving a half billion requests per day with Rust and CGI

#60

How meaningful is “per day” as a performance metric?

It was traditional 30 years ago to describe web site traffic levels in terms of hits per day, perhaps because "two hundred thousand hits per day" sounds more impressive than "2.3 hits per second". Consequently a lot of us have some kind of intuition for what kind of service might need to handle a thousand hits per day, a million hits per day, or a billion hits per day.

As other commenters have pointed out, peak traffic is actually more important.

Post reply on HN