Llogiq, a Rust developer, writes about Rust performance, comparisons with Java, and how to write idiomatic Rust.
HN commenters cite his posts in discussions of Rust speed, garbage collection versus manual memory management, and the borrow checker.
Since I'm lazy, I'll point out that most of the stuff is indirectly mentioned in this write-up: https://llogiq.github.io/2015/10/03/fast.html
This reminds me I haven't written up stuff for chameneos-redux, which is probably the most fun and over-engineered of them all.
The fasta/Haskell thing I was mentioning are the parts at "The Haskell code does a quite clever alternative" and "the Haskell code just caches them all in an array".
The pre-compacting I mention in k_nucleotide was already done in the Scala implementation.
How parallelism is added also varies. The Scala code does each of the test cases in parallel whilst the Rust parallelizes each internally. (My new Rust code parallelizes even better.)
Several implementation make their own specialized hash table, and there isn't one particular hash table to implement. This is very important since hash table lookups take a substantial fraction of the time.
Note that I pick on Haskell and Scala here only because they have the best hacks, not because they're the only ones doing hacks. (I'd imagine listing all of the differences would take much longer than I have time for.)
thread-ring has lots of different implementations. Some are just scheduled coroutines restricted to a single process, then you have stuff like [1] which uses mutexes, real threads and sets thread affinity. I'm not totally sure what [2] is but I think it's something else entirely. I'm not being too specific here because honestly this benchmark confuses…
> there's even a book teaching how to implement doubly linked lists in Rust [1]
Doubly-linked lists are an awkward example because the "safety" of a doubly-linked list as a data structure involves fairly complex invariants that Rust can't even keep track of at this point, much less check independently. These things are exactly why the unsafe{} escape-hatch exists and is actively supported. But just looking at the amount of unsafe code in common Rust projects should suffice to figure out that this is not the common case, at all.
> At the same time, people are using Rust to build non-systems programs, where other languages would be more appropriate (e.g. those with garbage collectors).
Garbage collectors are good for one thing, and one thing only: keeping track of complex, spaghetti-like reference graphs where cycles, etc. can arise, perhaps even as a side effect of, say, implementing some concurrency-related pattern. Everything else is most likely better dealt with by a Rust-like system with optional support for reference counted data.
That's without even mentioning the other advantages that a Rust-like ownership system provides over a GC-only language. See e.g. https://llogiq.github.io/2020/01/10/rustvsgc.html this recent post for some nice examples.
> You could use LLVM to compile any language to LLVM IR, and then to machine code using a backend. Does that mean every language has the same properties as Rust?
Nope, it's largely depend on the language design.
> If Node/Java/Go use GC (or VMs), then aren't they more safe than Rust?
Yes and No, memory allocation is one of the issue in GC. Go is generally more safe on networking but not security where Rust can manage it securely.
This is a good read on Java vs Rust: https://llogiq.github.io/2016/02/28/java-rust.html
https://news.ycombinator.com/item?id=14173716
https://github.com/stouset/secrets/tree/stack-secrets
In fact, we don't have to bother much with GC because it's depend on programmers and job availability. GC was created based on the idea that manage memory is hard for large scale project. It work well for Azul Systems, and they have recently advertised for LLVM engineer to bring more performance where JVM could not.
> Rust programmers tend to do all kinds of little hacks here and there to make the borrow checker happy. It can add up. The borrow checker is perfectly happy when you copy everything.
Do you mind sharing an example? If you're talking about using to_owned or clone without reason, then it's fully on the developer.
Some more pitfalls to avodi: https://llogiq.github.io/2017/06/01/perf-pitfalls.html
What you say definitely doesn't match my experience.
I would say Java code and Rust code are roughly in the same order of processing speed but the JVM "wastes" some memory. You also have garbage collection complicating performance in some scenarios.
I'm pretty sure you can get in the same processing speed ballpark with careful programming in both languages.
Outperforming C++ is definitely harder but Java should be doable.
Even if you're one of those people who believes the highest levels of performance require manual memory management (I'd disagree, but whatever), you'd do well to consider the performance of real-world GC against performance of the Arc/Box/dyn/clone-heavy "high-level Rust" [1] [2] that people and LLMs usually write.
Maybe you can write a carefully-tuned arena-and-slotmap that beats the pants off any GC. GC doesn't have to compete against P99.9 systems programming excellence. It has to compete against an endless soup of Arc, Box, and clone, and it will win this match without breaking a sweat.
[1] https://hamy.xyz/blog/2026-01_high-level-rust
[2] https://llogiq.github.io/2020/05/30/hi.html
> I've been watching Rust on that Benchmarks Game site for a while — it's been interesting to see it go from worse than Java a year or so ago to competitive with C++
To be clear, Rust-the-language has not sped up significantly in the past year. It's just that a few dedicated people decided to try to win the benchmarks game strictly for PR purposes [0].
Chances are, for very algo-heavy (i.e. unrealistic) workloads, there are two ways to write it in Rust - fast and safe or very fast and unsafe. (e.g. one can disable bounds checking and get maybe a 2% speedup).
All this really serves to show is how artificial the benchmarks are.
[0] https://llogiq.github.io/2015/10/03/fast.html