Ask HN: Rust vs. Julia
Hypothetical: I have a professional contract to fulfill where I'm given freedom to choose what programming language I use to build a library that will be used in an application. The library will require a large number of matrix operations and will require taking advantage of parallelization wherever possible. I plan to focus on building the GUI at a later stage, once the core library has been completed. This software will be used by consumers heavily in 2020. Given only this information, what language would you choose to tackle this problem? Julia or Rust?
8 comments
[ 0.26 ms ] story [ 33.3 ms ] threadPersonally if it were up to me I'd pick D (I'm just comfortable with D) if parallelism is a concern it covers that spot. However, for the sake of answering your question I'm more inclined towards Rust.
Rust has a growing community around it, has been tried and tested not only in the back-end but I write this response on a browser deployed to millions of users who are unknowingly running Rust across different operating systems, from Mac, to Windows, all the way to Linux. Rust has a strong package manager and they're investing in their core tooling which I think is a must for any programming language (and documentation).
Julia is also fascinating and I can admire Julia but I have not heard of deployments like Rust has achieved, and I would love to hear more about Julia out in the wild.
Rust does "feel" like a lot of overhead in order to avoid the GC. Can you comment on / know how I can check whether the GC in Julia is going to cause an issue for me?
Might be worth adding, Rust's ownership model isn't just to avoid GC. It ends up solving several problems at once:
- Thread safety. This one is huge. The Rust compiler knows when you're giving multiple threads racy access to the same object, and it prevents that at compile time. The trait system (Send and Sync) is a big part of this, but the ownership model is crucial too. Many languages that use GC to avoid dangling pointers, like Java and Go, can still invoke undefined behavior if you write a data race.
- Destructors. Sure, Rust has destructors because it doesn't have GC, but they're also a feature in their own right. Rust supports C++ style RAII without needing a defer/with/using statement; an API can add cleanup without "bubbling up" through all of its callers. It also means you don't have to worry about weird scenarios where finalization happens in an order you don't expect (see e.g. https://golang.org/pkg/runtime/#SetFinalizer, https://docs.python.org/3.6/reference/datamodel.html#object....). Destructors are great, and the ownership model makes them safe.
- Less need for defensive copies and immutable collections. Big Python and Java programs often rely on these to avoid bugs where one part of a program mutates something that another part wasn't expecting, especially across threads. Rust's ownership model means that functions are explicit about when they have permission to write to some object, and when they might be stashing a reference for later. If you write a function that takes `&mut HashMap`, you have a guarantee that no one else will write to (or read from!) that map until you're done, and the compiler will make sure your callers uphold that guarantee.
Julia is for research, Rust is for products.
I do need to choose one, given the time and budget that I will have to work on this. I do understand that if there are things that I cannot do in Julia, I would be able to call out to a Rust shared library using FFI, but I don't expect my use case to need it. I'm likely going to have to build a library that can be called from Julia/Python/Java etc. The question is whether to build that library in Rust or Julia. Rust has more solid C ABI support at the moment. But I'm hoping PackageCompiler.jl and other niceties come along and make the Julia shared library interlop better too.