this post was submitted on 26 Feb 2024
267 points (96.5% liked)
Programming
17432 readers
220 users here now
Welcome to the main community in programming.dev! Feel free to post anything relating to programming here!
Cross posting is strongly encouraged in the instance. If you feel your post or another person's post makes sense in another community cross post into it.
Hope you enjoy the instance!
Rules
Rules
- Follow the programming.dev instance rules
- Keep content related to programming in some way
- If you're posting long videos try to add in some form of tldr for those who don't want to watch videos
Wormhole
Follow the wormhole through a path of communities [email protected]
founded 1 year ago
MODERATORS
you are viewing a single comment's thread
view the rest of the comments
view the rest of the comments
Rust does memory-safety in the most manual way possible, by requiring the programmer prove to the compiler that the code is memory-safe. This allows memory-safety with no runtime overhead, but makes the language comparatively difficult to learn and use.
Garbage-collected compiled languages — including Java, Go, Kotlin, Haskell, or Common Lisp — can provide memory-safety while putting the extra work on the runtime rather than on the programmer. This can impose a small performance penalty but typically makes for a language that's much easier on the programmer.
And, of course, in many cases the raw performance of a native-code compiled language is not necessary, and a bytecode interpreter like Python is just fine.
I'm no Rust expert, but in what I have done with it I've always found it reassuring to know the compiler has my back, and I haven't found the rules too onerous. In some ways I prefer this to counting on some black-box garbage collector with unpredictable performance costs, and I certainly prefer catching as many errors as possible at compile time not runtime.
A better approach is the one Apple uses with Swift (and before that, Objective-C... though that wasn't memory safe).
In swift the compiler writes virtually all of your memory management code for you, and you can write a bit of code (or annotate things) for rare edge cases where you need memory management to do something other than the default behaviour.
There's no garbage collection, but 99.999% of your code looks exactly like a garbage collected language. And there's no performance penalty either... in fact it tends to be faster because compiler engineers are better at memory management than run of the mill coders.
To be fair, Swift uses reference counting instead of garbage collection which has different tradeoffs than GC but does incur a performance penalty.
I wish more languages used ref counting. Yes, you have to be careful of circular refs, but the tradeoff is simplicity, speed, lack of needing threads in the runtime, and predictability. Rust gives you special data structures for ref counting for a reason.
Ref counting is just a very basic GC. I'd be surprised if a ref counted language performed better than a GC one. Sure, the program won't temporarily halt in order to run the GC, but every copy/destroy operation will be slower.
When Apple introduced the iPhone they required automatic reference counting to be used in Objective-C rather than tracing garbage collection (the language supported both) due to performance reasons (iPhones were significantly slower than Macs). At least Apple seems to think that reference counting is faster than tracing garbage collectors. The compiler can do a lot to remove unnecessary releases and retains. Additionally each retain is just incrementing an integer, and each release is just decrementing an integer and comparing the integer to 0, so the overhead is pretty small.
If the compiler optimizes away some RC then I see how it can be faster.
The most manual way is what C does, which is requiring the programmer to check memory safety by themselves.😛
Also will say that outside of some corner cases, Rust is really not that harder than Java or Python. Even in the relatively rare cases that you run into lifetimes, you can usually clone your data (not ideal for performance usually but hey its what the GC language would often do anyway). And reliability is far better in Rust as well so you save a lot of time debugging. Compiles = it works most of the time.
Software engineer for almost two decades at this point, programming off and on since a kid in the late '80s: Rust is harder. It did seem to get better between versions and maybe it's easier now, but definitely harder than a lot of what I've worked in (which ranges Perl, PHP, C, C++, C#, Java, Groovy/Grails, Rust, js, typescript, various flavors of BASIC, and Go (and probably more I'm forgetting now but didn't work with much; I'm excluding bash/batch, DB stored procedures (though I worked on a billing system written almost entirely in them), etc.)
That said, I don't think it's a bad thing and of course working in something makes you faster at it, but I do think it's harder, especially when first learning about (and fighting with) the borrow checker, dealing with lifetimes, etc.
The availability of libraries, frameworks, tools, and documentation can also have a big impact on how long it takes to make something.
I like Rust a lot, philosophically and functionally... but it is WAY harder. Undeniably very hard.
Just try and do anything with, say, a linked list. It's mind-boggling how hard it is to make basic things work without just cloning tons of values, using obnoxious patterns like
.as_mut()
, or having incredibly careful and deliberate patterns oftake
-ing values, Not to mention the endless use of shit likeBox
es that just generates frustrating boilerplate.I still think it's a good language and valuable to learn/use, and it's incredibly easy to create performant applications in it once you mastered the basics, but christ.
It's mind-boggling how broken basic things are.
I have not encountered anything broken, aside from maybe binary app docstring stuff (e.g., automated example testing).
On the contrary, everything seems precise, reliable, and trustworthy. That's the thing to really like about Rust -- you can be pretty much fearless in it. It's just difficult. I die a bit in time any time I have a return type that looks like
Box<dyn Fn(&str) -> Result<Vec<String>, CustomError>>
or some shit . Honestly, the worst thing about Rust is probably that you have to manually specify heap vs stack when the compiler could easily make those determinations itself 99% of the time based on whether something is sized.C# dev with reasonable experience with java, python, and rust:
Rust is harder
The difference is, Rust will throw a tantrum if you do things in an unsafe way. C/C++ won't even check. It'll just chug along.
As someone who's done all three, the fuck it isn't.
If you are familiar with C/C++ best practices to any operational level, those things will translate over to Rust quite nicely. If not, that learning curve is going to be fucking ridiculous with all the new concepts you have to juggle that you just don't with either Java or Python.
I haven't been able to compile a single C/C++ program (even bought a C++ book!) Learned to write normal programs in rust (even with simple lifetime annotations!) In 1-2 months. I just knew python and the basic knowledge of 1st year university.
It's not that hard.
Just reading through the rust book (a week, maybe? I don't remember how much time it took) will make you able to confidently write a simple CLI program.
You can do the same in Java or especially Python from zero much, much quicker.
Also you can learn to go beyond simple CLI programs in those languages much quicker, because you don't have to worry about memory management.
I'm not saying that java or python are harder, of course they aren't. I'm just saying that it's not as hard as people seem to think. What is 1 week of commitment to learn a new language? Of course it depends on what there is to offer.
I think the benefits of rust far outweigh it's drawbacks (including the learning time).