They didn't mention Java as a possible solution, even though its GC's are far better than anything else out there. I have nothing against Rust but if I was at a startup I would save my innovation points for where they're mandatory
Ah yes, a 236 word "article", that says to choose "boring old technology" and also to use Rust in the same breath.
This article should mention that rust isn't close to ready when it comes to web backends. As much as I love Rust, if I were running a startup or even a decently sized company I would always choose Rails. Now -that- is boring, old... and mature technology. Certain components could get re-written in Rust, certainly, but there's no reason to ignore a mature ecosystem from the start.
> This article should mention that rust isn't close to ready when it comes to web backends.
Actix-web works just fine. They got a new maintainer team involved that has been spending some time getting rid of all the insane unsafety that was in the code before.
Yes. It "works". However deciding to use Actix/Warp means throwing away years and years of work in the rails and ruby world.
Rails is mature, robust, and has a huge ecosystem with rubygems. Rust (when it comes to web stuff) is not. "it works" does not pass my litmus test. With Actix/Warp I have to implement stuff by hand that either comes by default with rails or already exists in a gem.
I like Rust but I'm not a zealot. People way overestimate performance when they barely have any traffic to begin with as a small startup or even a medium sized company.
You could even use rails, and use Rust to write ruby gems instead of going with actix/warp/etc.
> insane unsafety
This was overblown. Yes, the author didn't respond appropriately, but unsafe isn't inherently dangerous. This is a stupid misconception within the Rust community and caused a lot of unnecessary drama around Actix.
One step beyond good Java GCs is to write fully zero-GC Java code. The advantage of it is complete control over your performance which means your software is going to be consistently fast. The disadvantage is that it is relatively difficult to obtain.
If you want to see an example of fully zero-GC Java, you can check out QuestDB on Github [1] - Disclaimer I work for QuestDB.
> One step beyond good Java GCs is to write fully zero-GC Java code. The advantage of it is complete control over your performance which means your software is going to be consistently fast. The disadvantage is that it is relatively difficult to obtain.
I don't know that it's actually possible in the general case, as Java's support for value types remains wholly insufficient. IIRC the ixy folks never managed to remove all allocations from the java version.
It's not like Elixir doesn't benefit from a battle hardened VM since it's older and has been used in these kind of high volume scenarios before Java was.
They ruled out a language because it had stop the world GC, and even if it removed the bottleneck, it would likely become one later. Java has the same issue. Rust does not.
Not sure why they'd consider Java, given that concern.
Shenandoah and ZGC collectors have worse case pauses of ~10ms and average pauses of 0.5ms . The average pause is faster than malloc() sometimes in C, so you won't really be introducing more latency than C does.
The other option is to avoid allocating memory at all, which you could do in C/Rust but also in Java. The vast majority of shops given the choice for low/no allocation performance use Java anyways (HFT)
But those GCs also don't guarantee all garbage has been collected, nor how much processing time you'll get before they run again. So op could still end up stuck with their code barely executing, due to memory and CPU pressure, and throughput/latency drops to zilch.
"The vast majority of shops" is an interesting metric given the vast majority had to pick a language before Rust existed. Java and trying to minimize allocations, vs C/C++, I'd probably choose Java too. Java trying to minimize allocations (no way to guarantee you've done it right), vs Rust (which does guarantee no GC)...I'd probably pick Rust.
> But those GCs also don't guarantee all garbage has been collected, nor how much processing time you'll get before they run again. So op could still end up stuck with their code barely executing, due to memory and CPU pressure, and throughput/latency drops to zilch.
You could malloc() and free() so much that the code doesn't have time to do anything too. And these operations aren't bounded in time either. Just using C doesn't save you from memory allocation, its just done manually instead of automatic. In every system I've worked on you won't have this kind of GC pressure unless you do something profoundly bad
> The vast majority of shops" is an interesting metric given the vast majority had to pick a language before Rust existed.
You could, sure. You could do (anything) and still block (other parts of the code). Point is, GC isn't necessary for executing code, malloc/free is (well, for non-trivial programs that have data whose size is unknown at compile time).
With GC, I've definitely had plenty of times where GC created very noticeable pressure on the running system. Nothing quite as bad as they describe here, true, but that would probably predispose me to ditching GC if I saw that kind of behavior, too (since it's so unlikely that either my case is truly deviant, or my devs have done something very wrong, and neither of those is something I want to bet on being able to fix).
GC is like malloc() but automated and done on multiple threads.
With how low the pause times are with Java's new collectors (categorically not longer than malloc()), the only faster alternative is not allocating at all. Which you can do in many languages.
I agree your point the memory allocation and GC is expensive, but that's something you see in any language when allocating. It's not unique to the GC. You either pay the price with GC or malloc()/free(). Its the same price but one is much easier to deal with than the other.
If pause times lower than 10ms are important you could write your app in Rust which makes it much easier to systematically avoid allocations using borrowing.
I guess my point is that the new collectors make Java memory management roughly comparable to C, and if you care so much about performance that allocation costs are important, you should just use a language like Rust where its easy to avoid allocation completely. The performance gap between allocating in C vs Java is, for practical purposes, gone.
They did mention Go that also has a modern GC, and does not need to run your app under a software VM. But ultimately, even Go is just another GC language. They had no real need for GC and the like so why use Go, let alone Java?
Go's GC is notoriously low tech. Its design dates back to papers published in the 70s. Java's Parallel collector is most similar to Go's GC and its deprecated for removal due to poor performance.
Go collects VERY frequently to keep average pause times low, which hurts throughput. It also has pathological worst-case pause times, which is what the author ran into.
My suggestion of Java is just because its been used for high performance REST for decades. Rust has Actix and a few other frameworks, in Java you have 20+ options. Its a lot easier to get something off the ground when you're 99% sure you won't have to build anything except some glue code. Yes, Rust is faster, but is 30% better performance worth treading the wilds while you're trying to keep a startup afloat, I don't think so personally.
Using Java with Shenandoah or ZGC collector would directly handle their GC issue with rather boring technology
Rust doesn't have a GC; it uses an ownership model instead.
Ultimately in a startup it comes to what people are comfortable with. I personally would use Rust for something like this because I am comfortable with Rust. It's a perfect use case for it as well, imho.