News for hackers. Stuff that matters.
Re:TechEmpower Framework Benchmarks: Round 20 by lstamour on Monday February 08, 2021 @03:04PM (#26069400)
I wrote this comment based on pre-release benchmarks, based on Physical benchmarks run against Git commits from Jan 23 - but it should still largely apply to the final benchmarks:

It’s kind of frustrating to spend a few hours investigating preview results of the latest techempower benchmarks just to come to the conclusion that (a) truly high performance requires tuning your code to linux, to the network interface cards, and a deep understanding of what your code is doing and (b) right now at the top of the benchmarks, common high performance Rust code is mostly “unsafe” memory-wise, and the same is true of C++ for obvious reasons. After that:

* When looking at garbage collected languages with very minimal implementations (Jooby mostly), Java can come out on top but requires 4 Gigs of memory which is more than I would ever like to use.

* After Java comes C# but performance slows down the second you want to do anything less optimized, like use third-party libraries.

* Finally, we’ve Go, which in a surprising twist is basically neck and neck with some pure PHP server implementations, but once I include those, I might as well mention there’s a JS implementation that skips the Node.js async event loop and offers performance on par with C++ and Rust, but heavily uses C++ internally and is thus more “unsafe”.

What this tells me is kind of what I expected, implementation matters more than language… at this point, memory usage aside for Java, an efficient HTTP/1.1 server can be implemented in basically any language and when tuned or stripped down tends to run faster than the commonly used web servers, like Nginx, Tomcat, Express, etc. Often this means writing plain text RAW HTTP to a socket and managing sockets efficiently.

Which brings us back to Go, though. Of all the implementations I’ve looked at so far, even the PHP one, only the Go benchmark is written like “standard Go” such that most people writing a service in Go will write something high performance without trying to make it high performance. Effectively, you don’t need to ensure all your dependencies use special optimized code routines to get something relatively optimized working quickly in Go with low memory overhead unlike Java.

I’m a bit shocked by this conclusion as I was really hoping that Rust’s high performance use cases would win out, as it’s true that Rust can get 3x faster than Go, but on the Rust side, both actix and ntex are too immature as neither’s hit 1.0 yet, while tokio has hit 1.0 but its server, warp, is slower than Go.

Irritating is that each of the techempower benchmarks use different implementations. For example, there’s a benchmark that’s supposed to measure 20 calls to Postgres, but one benchmark gets to the top by making only one long SQL statement that changes 20 rows. Another implementation uses pgx’s Batch functionality to send multiple queries in batches (a big timesaver, but not technically standard libpq), but then the standard Go variant doesn’t use Batching even when it could (which means we can’t compare custom implementations to generic Go ones fairly): https://github.com/TechEmpower/FrameworkBenchmarks/search?l=...

Re:TechEmpower Framework Benchmarks: Round 20 by Twirrim on Monday February 08, 2021 @05:42PM (#26071299)
> For example, there’s a benchmark that’s supposed to measure 20 calls to Postgres, but one benchmark gets to the top by making only one long SQL statement that changes 20 rows.

That seems like a clear cheating case, over-optimised to the circumstances of the benchmark.

Re:TechEmpower Framework Benchmarks: Round 20 by dmm on Monday February 08, 2021 @05:05PM (#26070848)
> right now at the top of the benchmarks, common high performance Rust code is mostly “unsafe” memory-wise

I only see a single "unsafe" in the Rust implementation[0]? And that's only in the "raw" Actix instance, not the pg. Or are you talking about Actix framework being mostly unsafe?

> only the Go benchmark is written like “standard Go” such that most people writing a service in Go will write

Maybe it's just me but the Actix apis seem pretty ordinary.

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

Re:TechEmpower Framework Benchmarks: Round 20 by lstamour on Monday February 08, 2021 @10:09PM (#26073405)
> about Actix framework being mostly unsafe

Yep, that's what I meant. To me, until Rust unsafe implementations hit 1.0 as web frameworks, not just Tokio, I can't consider them as stable or bug-free as more mature web servers. It's arbitrary, yes, but it's also an important distinction. 1.0 generally means "you can rely on this to not change, and to have a useful set of functionality" and bug fixes equivalent to an LTS release. This is especially true if functionality is common enough that it makes its way into a standard library or conventional best practices. Generally, it has to hit "1.0" before it does so, though, in any stable manner...

Re:TechEmpower Framework Benchmarks: Round 20 by covidthrow on Tuesday February 09, 2021 @12:55AM (#26074341)
The Actix unsafe code has long since been resolved. There are very few instances of it, and each are small, specific, easy to reason about, and wholly internal. I'd guess the risk is about on par with—or safer than—VM runtime languages written in C/++.

Far as 1.0 in Rust, the predominant culture is to treat "0.X.x" releases roughly equivalent to a "1.x" semantic. I have run into very few issues of API breaking changes in "0.X.x" libraries, and even those are basically handed to you thanks to Rust's robust compile-time checks.

Of course your mileage may vary, but I've had a way worse time with even well-established breaks in Ruby, Python, and Go libraries. I understand your risk aversion; I am similar. But I've found Rust to be an absolute delight for stability. The shaky ground of the first few years has largely given way to impressive robustness over the last few.

I strongly urge you to consider Rust if it matches your needs. You may be quite pleased!

Re:TechEmpower Framework Benchmarks: Round 20 by lstamour on Tuesday February 09, 2021 @02:35PM (#26081583)
The 0.x stability is news to me. I would suggest the community would get wider adoption by moving to 1.0 for components that others can build on, such as web servers.

To me, that Tokio hit 1.0 is a significant milestone, one that encourages its use for new projects. I personally look forward to the first web server widely adopted that hits 1.0 and relies on an async implementation that’s also 1.0…

I agree that Rust is very attractive, but it’s hard for me to argue for Rust against Go’s stability if you can live with Go’s more limited syntax. If Rust could promise the same stability as you’d have writing a JSON API or HTML-templates website in Go, I’d start picking Rust for new projects.

My perspective, to be clear, is that the heisenbugs likely still exist in Rust servers but have been mostly ironed out in Go ones. I’m reminded of Hyrum’s Law - https://www.hyrumslaw.com/ - under the assumption that as libraries hit 1.0, their behaviour can be more reasonably relied upon than pre-1.0…

Re:TechEmpower Framework Benchmarks: Round 20 by roca on Monday February 08, 2021 @07:11PM (#26072160)
> on the Rust side, both actix and ntex are too immature as neither’s hit 1.0 yet

Maybe so, but we've been running https://pernos.co on Actix for a couple of years now with no issues. We didn't have to use "unsafe" either, and I understand that Actix's use of "unsafe" internally has also been significantly reduced.

Tokio's "warp" is much less mature than Actix AFAICT. Version numbers can be misleading.

Re:TechEmpower Framework Benchmarks: Round 20 by lstamour on Monday February 08, 2021 @10:21PM (#26073465)
That's a good point. And since AWS put forward their support for Rust recently, along with Microsoft's interest and the new Rust Foundation, the future is looking rather bright for Rust. But it reminds me still of the early days of React, the early days of TypeScript, or the early days of Apache, or PHP before Laravel, when there was room for a lot of competition and the "best practices" had yet to work themselves out.

Part of it is that Rust as a language moves quickly, I agree, but there's right now a lot of confusion between picking the pre-1.0 Actix or the post-1.0 Tokio, with AWS seemingly endorsing Tokio but with practical web development restricted to Actix Web for now. This confusion highlights the risky nature of pre-1.0 web servers -- it's not that you can't be productive and stable, but you might need to keep living on the edge for a long time. If you have a small service, that's fine. If you're looking for an API that won't change for 3 years or more, it's harder to suggest Rust at this time...

Re:TechEmpower Framework Benchmarks: Round 20 by kristjansson on Monday February 08, 2021 @06:39PM (#26071898)
> truly high performance requires tuning your code to linux, to the network interface cards, and a deep understanding of what your code is doing

With absolutely no snark intended: what alternative do you see (or imagine) to this? Applying quite a bit of mechanical sympathy to tune a program to the system and visa versa seems essential and inescapable.

Re:TechEmpower Framework Benchmarks: Round 20 by lstamour on Monday February 08, 2021 @10:13PM (#26073417)
The incorrect alternative I meant is the idea that you can "just switch languages" or frameworks and get an instant speed boost. I mean, yes, sometimes your web server, caching proxy or CDN can act as a silver bullet, and rewriting can provide its own benefits if it simplifies the code, but assuming one language is better than another because "it ranks higher" is only one way of looking at the problem. It's more important to consider other factors, from low-level Linux to high level system architecture, perhaps with something like OpenTelemetry to pinpoint distributed hotspots, for example. Yes, you can learn something from these benchmarks, but alone benchmarks and frameworks can't speed up your app. :)
Re:TechEmpower Framework Benchmarks: Round 20 by AtlasBarfed on Tuesday February 09, 2021 @01:19AM (#26074470)
What's jooby doing with 4 gigs? a massive arena allocation to avoid gc?
Re:TechEmpower Framework Benchmarks: Round 20 by lstamour on Tuesday February 09, 2021 @02:37PM (#26081599)
I suspect so, yes. The commit history doesn’t say, but maybe the benchmarks from that time would… https://github.com/TechEmpower/FrameworkBenchmarks/commit/cf...
Re:TechEmpower Framework Benchmarks: Round 20 by newlisper on Monday February 08, 2021 @04:00PM (#26070037)
Where did you see memory consumption results?
Re:TechEmpower Framework Benchmarks: Round 20 by billywhizz on Monday February 08, 2021 @04:03PM (#26070079)
there's a nice tool here for visualising the results in more detail... https://ajdust.github.io/tfbvis/?testrun=Citrine_started2020...