I've done a lot of benchmarks of Julia against C++, and I'm pretty sure its possible to reach exactly the same performance as Rust in most cases. Memory efficiency is a whole different thing, so I think it's fair to say that Julia will have a pretty hard time to reach the same efficiency there in most programs. In some areas, that translates to worse performance, especially multi threaded code, but I've at least always been able to reach optimal performance. Since Julia is compiled statically at runtime with the same LLVM compiler as Rust, I'm pretty sure it's accurate to say, that Julia can (maybe with extra work) reach the same performance as Rust in 99% of the cases.
Also it seems pretty "unfair" not to mention, that Julia's whole big selling point is zero cost abstractions as well...
And it's absolutely not true, that one needs to write for loops in Julia for best performance. Not sure where that comes from? I think this hasn't been the case since Julia 0.4, so ages ago.
I'd love to add some more thoughts, but they would be more complex to add to the website.
E.g. it seems crazy to me, to say that Rust refactors are smooth sailing compared to Julia, just because you get compiler errors.
I can refactor huge code bases in Julia by changing things iteratively, while getting runtime errors that tell me exactly what still needs work, without ever needing to recompile my whole project. It's amazing to me, that I interactively can debug refactors with real data instead of abstract compiler errors and helps me do gigantic refactors e.g. in Makie, which is a huge project.
There's also https://verdagon.dev/blog/when-to-use-memory-safe-part-2 pointing out quite nicely, how Rusts memory model makes certain refactors so hard, that the whole project isn't possible:
Looking closer, it's largely because the borrow checker imposes extra constraints compared to other paradigms, such as the constraint that you can't have multiple mutable references to an object. 15 When you want to make a change, you can't just do the simplest change, you need to find a change that also satisfies the extra constraints of the borrow checker.
The borrow checker also runs into some problems with decoupling. From Using Rust at a startup: A cautionary tale: 16
What really bites is when you need to change the type signature of a load-bearing interface and find yourself spending hours changing every place where the type is used only to see if your initial stab at something is feasible. And then redoing all of that work when you realize you need to change it again.
From talking with quite a few Rust programmers, this doesn't only seem academically, but a real problem for large Rust projects!
I also don't really understand, how doing Float64[] instead of [] seems like a huge footgun, while using one of the most complex memory models that exists (borrow checking) which strongly constrains your whole way of programming, seems to be a super easy thing to just adopt ;)
But I guess, some people just like to be much more constraint in order to not need to manually check a few type instabilities. So not sure how I would add this to your blogpost, to make it more balanced ^^
Anyways, thanks for the post, these are all just comments to turn this into a more generally usable resource to compare Julia with Rust, instead of it being just a subjective comparison.