4 ms·
Pardon my ignorance, but I thought the whole point of Rust was to be a 'safe' modern alternative to C, so all new buffers would be zero'd at a neglible-these-da
by briansm 1y ago
Pardon my ignorance, but I thought the whole point of Rust was to be a 'safe' modern alternative to C, so all new buffers would be zero'd at a neglible-these-days cost. Why is rust half-assing this?
- vlovich123 1y agoIt’s not. That is the case. But in cases where “negligible-these-days” isn’t quite negligible enough, this still matters and unsafe + MaybeUninit is the escape hatch to accomplish it.
- Arnavion 1y agoAlso not every type has a valid "all zeroes" value in the first place.
- briansm 1y agoYuck. In my mind, 'using C and not using Rust in the first place' is the escape hatch and Rust shouldn't even go there. Jeez, what a mess.
- JoshTriplett 1y agoThis is why we're spending substantial energy building better abstractions that don't require you to write any unsafe code.
- vlovich123 1y agoRust provides all the safety guarantees of managed languages with none of the performance drawbacks. It’s precisely intended to replace C/C++ because the unsafe parts of Rust are used very sparingly and result in significantly fewer bugs and security vulnerabilities. Safe abstractions for dealing with uninitialized memory efficiently are important in very niche scenarios to get optimal code out of the compiler and for reducing the ability to make a mistake when writing such code. Reaching for C to do this is an emotional overreaction instead of calmly dealing with a small corner case that already has workarounds even if it does involve using unsafe
- cozzyd 1y agowhat if your buffer is 64 GiB? (ok, in practice it will be zero'd on demand by the OS but still)
- josephg 1y agoI’d love to know the actual performance impact of zeroing out memory. I bet the performance cost of zeroing out memory ahead of time is negligible in almost all programs.
- cozzyd 1y agoHere is a really dumb example: $ cat bigbuf.c #include <stdlib.h> #include <stdio.h> #include <string.h> #define DEFINITELY_BIG_ENOUGH 2U*1024*1024*1024 int main(int nargs, char ** args) { char * definitely_big_enough = malloc(DEFINITELY_BIG_ENOUGH); if (nargs > 1) { memset(definitely_big_enough,0, DEFINITELY_BIG_ENOUGH); } sprintf(definitely_big_enough,"%s",args[0]); return 0; } $ /usr/bin/time ./bigbuf 0.00user 0.00system 0:00.00elapsed 100%CPU (0avgtext+0avgdata 1356maxresident)k 0inputs+0outputs (0major+80minor)pagefaults 0swaps $ /usr/bin/time ./bigbuf 1 0.05user 1.25system 0:01.31elapsed 99%CPU (0avgtext+0avgdata 2098468maxresident)k 0inputs+0outputs (0major+524369minor)pagefaults 0swaps YMMV on different operating systems. Of course this is a program only an idiot would write, but things like caches are often significantly bigger than the median case, especially on Linux where you know there is overcommit.
- Arnavion 1y agoA non-idiot would use calloc(DEFINITELY_BIG_ENOUGH), and that will likely erase the difference because the impl will be able to rely on mmap(ANONYMOUS) creating zero pages for such a large allocation. A more realistic test would be to have a large number of small allocations that get calloc'd and then free'd repeatedly, because a) free'ing a small allocation will not free the underlying page and thus reallocation will not be able to rely on it already being zero, and b) zeroing small allocations doesn't amortize the cost of zeroing as well as zeroing large allocations does.
- arlort 1y agoThe cost might not be negligible for everyone? Rust is being used and is designed to be able to be used everywhere from top of the line PCs, to servers to microcontrollers to virtual machines in the browser. Not all tradeoffs are acceptable to everyone all of the time
- mrkeen 1y agoOther languages can easily achieve this kind of safety. What makes Rust different is that it tries to provide this level of safety without doing extra work at runtime (because otherwise people will put it in the same pile as Java/C#, and continue using C/C++ for speed).