Poll - how much do you use unsafe to "go faster"?

  • Pretty much never
  • Sometimes
  • Frequently
0 voters

My general perception is that Rust discourages the use of unsafe to "go faster", but of course it could be justified in some cases, but I think they would be quite rare, and most people do not use it frequently or even at all. Besides voting, please reply and give examples of where you used it, and why it was justifiable ( if you think it was ), or confess that it wasn't!

"Go faster" isn't a reason to make an unsound API, nor to make everyone deal with an unsafe one.

To wrap that unsafe stuff in a sound safe interface, though? That's the essence of Rust.

3 Likes

Hm, I first voted “sometimes”, but after some thinking it looks like I did not use unsafe for specifically execution speed in any projects I actually used. So far I used unsafe in about three cases:

  1. My first Rust project was STM32-based UART to CAN converter back in 2018 when pretty much no relevant HALs existed and in addition to that being my first Rust project (meaning I had no confidence in my ability to write HAL I needed) I also expected to use the results in relatively short while, so I opted to not writing HAL myself which meant using unsafe for every interaction with special-purpose registers. (Project ended up not working too well and for the next time I needed CAN support I just wrote code in LabVIEW’s G for use on FPGA, saved me from needing to have CAN transceiver on board.) I have rewritten it recently using modern HALs just to see how good they are, it appears that I no longer need unsafe code for the task, though some bxCAN functionality is missing from Rust drivers. (No idea whether rewrite actually works though.)
  2. Second time I decided to use unsafe is rewriting my LabVIEW flatten to string output parser (note: not on crates.io) to use serde in place of my own variant of what is essentially Deserialize trait. And making it work with no_std and without alloc for most functionality for no particular reason aside from being more challenging. This attempt has some types like String replacement which uses buffer with static size unless you enable use of alloc and unsafe code is pretty much only handling of MaybeUninit so that I do not have to initialize that or similar buffers. Should I actually do finish the port I am sure I am going to only use it with both alloc and std support, but it actually has unsafe used for optimization purposes.
  3. In similar fashion I used uninitialized buffers when checking how hard it would be to create bindings to some NI libraries in Rust. That never gone anywhere, and additionally reading into uninitialized array is not a problem without crates lying around offering a solution to, I am probably going to use them rather then write unsafe code myself in the future.
1 Like

Where is the "Never" option?

I have used unsafe when accessing hardware peripherals. Of course, there is no other way.

I have used unsafe when calling into C code. Of course, there is no other way.

I have been tempted to use unsafe for performance on occasion, but really the gains were marginal and hardly show up in an overall application of mine.

Bottom line for me is that if you really need unsafe then you have no choice. If you want unsafe for performance you have to make a good case for it.

1 Like

I found this use of unsafe in the Serde crate:

I wouldn't say it was controversial, but clearly some people like to monitor the usage of unsafe in their dependencies.

That kind of unsafe I'm hoping we'll be able to avoid more and more with Add `ascii::Char` (ACP#179) by scottmcm · Pull Request #111009 · rust-lang/rust · GitHub

There's lots of code that's "obviously" only writing ASCII to a buffer, but there's no way to prove that through the type system in std today, which leads to understandable use of unsafe because "yes what you pushed into that Vec is valid UTF-8" is the kind of thing that LLVM cannot realistically prove on its own.

2 Likes