5 ms·
Do people generally say they need a lot of unsafe? Hasn't come up much for me. Also I'm not sure the cognitive overhead is really that big. The compiler helps
by lordnacho 3y ago
Do people generally say they need a lot of unsafe? Hasn't come up much for me.
Also I'm not sure the cognitive overhead is really that big. The compiler helps a lot with its useful error messages.
- slashdev 3y agoDepends how much performance matters and what the problem domain is, and how low level it is. It can vary a lot.
- andrewfurey2003 3y agoBeen using ash for vulkan so lots of unsafe here
- ActorNightly 3y agoIf you chose Rust because you want speed that comes with natively compiled code, and you want optimal performance, in general you will probably come across a place where you need to dereference pointers without anything extra running.
- jjnoakes 3y agoI haven't really had this experience. Usually a subtle reorg of how I iterate, for example, allows the compiler to eliminate bounds checks, effectively giving me full speed without unsafe in tight loops.
- jamesmunns 3y agoFor what it's worth: references in Rust (both `&` and `&mut`) are just pointers with stronger static (compile time only) analysis. They have zero runtime impact vs raw pointers. Even heap allocations like `Box` are still just pointers, that have destructors that run when they fall out of scope, but access is just a pointer dereference, the same as you could do with unsafe.
- mtsr 3y agoIndeed. Raw pointers are mostly when either crossing FFI barriers (say, calling or being called by C) or when what you want to do can’t be expressed within Rust’s ownership rules without taking on overhead (Rc, cloning, indirections, etc) that’s unacceptable to your specific use case.
- ActorNightly 3y agoIf you are just working with data, you can avoid unsafe completely. The issue is that for performant code, you often have to tap into linux libc stuff which doesn't guarantee safety. For example, if you try to to write something with packet_mmap for fast processing of traffic, you will have to use unsafes. Look at the Firecracker codebase. There are a lot of unsafe calls into libc. There is also a runtime reference counter which takes up cycles since it has to operate at run time.
- __jem 3y agoOkay, but using unsafe for FFI is entirely different than the claim that you can only achieve performance optimizations through "dereferencing pointers without anything extra running." The use of unsafe for FFI is unavoidable for obvious reasons.
- sophacles 3y agoThere's nothing "extra running" when you dereference a rust reference either, its just a pointer that follows the semantics that can be checked at compile time.
- EnergyAmy 3y agoI've used some unsafe, but only when using Rust for embedded programming. The amount of unsafe I have to use is surprisingly low, since a lot of what I'd have to use it for is wrapped up into libraries like RTIC or the various hal/pac board-specific libraries.
- sophacles 3y agoA lot of people say that they need it because they are trying to code C in rust. Often I see it as analogous to trying to learn an SOV spoken language but insisting on using SVO grammar still - sure you can muddle through to a mutual understanding with a conversant, but it's high friction and has a lot of confusion along the way. I'm not trying to invalidate all claims that unsafe is necessary, nor even that there are cases where unsafe is quite helpful for performance. It's just that a little unsafe used deliberately and thoughtfully can go a long way, and accomplish those goals in a largely safe codebase.
- chriskrycho 3y agoI mostly hear it from folks who are explaining why they use Zig or Odin instead, or aren't why they are not interested in switching from C or C++. Re: overhead—I think the compiler helps a ton here, but I do think that it makes a lot of memory-related concerns explicit where they are usually implicit, and dealing with lifetimes can be quite burdensome. Now: I also think that those concerns still exist when you're using other systems-level languages, and that the tradeoff therefore often ends up looking like "Deal with it up front, or deal with it on hard mode later."
- josephg 3y agoI’ve spent a fair bit of time in rust and written more than my fair share of unsafe code. Unsafe is super necessary sometimes. But there are definitely reasons I’d consider using Zig or C or something if I needed a lot of unsafe in my project. - From a language point of view, the syntax for dereferencing pointers in rust is awful. I don’t mind the unsafe keyword. But in rust you can’t do a->b. You need to write (*a).b. And that gets increasingly awful as you have more complex pointer expressions. Unsafe code in rust looks significantly uglier than the equivalent C. - The Rust community - particularly on Reddit - seems to get very snide annd condescending about programmers using any amount of unsafe in their rust code. Even when it’s totally necessary. I’m not convinced the community will is there to fix rust’s bad pointer syntax, or other missteps with unsafe. Apparently having unreadable unsafe code is my atonement for wanting high performance code. Never mind that the harder my code is to read, the more likely I am to make mistakes. And in exactly the part of my codebase where bugs would be the most damaging to safety! Argh. I love rust. I love the fresh ideas it’s brought to programming as a whole. But I can’t wait for some other, newer languages to iterate on these features & the language syntax some more. It’s not the top of the mountain.
- estebank 3y ago> But in rust you can’t do a->b. You need to write (*a).b. For what is worth, I think that we'll add that at some point.
- mtsr 3y agoI think some of the snideness is probably due to different senses of what amount of unsafe is actually needed. There’s so much premature optimization in many cases that wouldn’t even come up if the language were Java, Go or whatever. It’s totally fine to initially accept some known overhead from cloning or Rc if you don’t know yet it it’s going to significantly impact performance.
- wokwokwok 3y agoYes. It’s pretty common to need to interact with existing APIs or libraries that only have a c interface. Fortunately, rust is good at that. Unfortunately, it’s impossible to do without unsafe code. You can wrap libraries in safe wrappers, or if you’re lucky someone has a wrapper you can use… …but I’ve heard it several times for this reason, especially in shops that have existing internal code bases (Ie. 0% chance of an existing safe wrapper) and want to incrementally adopt rust. Never heard someone say it’s because of perf tho; that sounds like a strawman argument to me; if your code is seriously too slow because of the bounds checking you’re doing something crazy and probably want to be using a gpu instead. It’s usually io bound, and unsafe code doesn’t fix that.
- zer8k 3y ago> The compiler helps a lot with its useful error messages. As someone trying very hard to love Rust this is just simply not the case. It takes the shortest path to most answers. The most trivial example where the compiler becomes less helpful is a self-balancing binary tree. It will constantly suggest explicit lifetimes and other magic when in reality you probably want `Box<Rc<..>>`. It will suggest Boxing for recursive types...but that's about the end of it. In many cases you're better off knowing what to do. But the problem is knowing what to do requires you to have done what you need...and hence the Rust Ouroboros is born. The nice thing about unsafe code (C, for example) is the cognitive overhead is initially very low. That allows you to get an idea down and then worry about stuff later. Of course, if you have a gun to your head from management you never get to the "worry about stuff later" stage and introduce all sorts of nasty bugs. Rust frontloads all of this making it sometimes very difficult to use without having everything already thought out way ahead of time. Both a benefit and a curse.
- mtsr 3y agoIt’s just the compiler assuming you know what you’re doing. You’re building this data structure on the stack, so it’ll point out where you’re not sufficiently explaining to it how the lifetimes of your code are safe. And even if you build it on the heap (using Box) you’ll still need to get the ownership right (using e.g. Rc). There’s only so many variations that work for something like trees (especially with doubly linked nodes) in any language, without either inherently unsafe lifetimes (because the particular language can’t express them as part of the API) or some kind of indirection (such as ECS style indices). Or garbage collection or ref counting, but one probably uses Rust to be able to control that kind of overhead instead of having to use whatever the language creators picked. If you want to learn about this, instead of using a ‘blessed’ implementation, read “too many linked lists” https://rust-unofficial.github.io/too-many-lists/ https://rust-unofficial.github.io/too-many-lists/. As for the front-loading comment: yes, Rust requires you to get some things right from the start, particularly ownership and lifetimes. If you want to work in Rust like in a scripting language, you can just use Box, Rc and clone() everywhere. But getting it right without those might require a significantly different API. Which isn’t that much different with your rough C implementation. To get any kind of safe API there will require just as many changes (if not more).
- jackmott42 3y agoDepends what you are doing, you might have 0.0 lines of unsafe, or you might be doing some custom SIMD string parsing code and its 100% unsafe. Or anywhere in between.
- insanitybit 3y agoI don't really need unsafe but I do enjoy using it. In particular, `unwrap_unchecked` is nice for when I'm 100% sure that an unwrap can't fail. I don't see any reason to leave that to the compiler to figure out.
- empath-nirvana 3y agoI've put a bunch of rust code into production and I've never written unsafe code. It primarily comes up when you're 1) interfacing with hardware 2) interfacing with C APIs 3) doing something weird with pointers.
- jandrewrogers 3y agoMost software does not need a lot of unsafe. There are a handful of software domains where you do need a lot of unsafe if you care about performance, but in these cases languages like C++ are often more ergonomic anyway.