4 ms·
Some months ago I ran into the same problem in slightly different clothing // 1st-way vec![0; len]; // 2nd-way std::iter::repeat(0).take(len).collect:
by erk__ 5y ago
Some months ago I ran into the same problem in slightly different clothing
// 1st-way
vec![0; len];
// 2nd-way
std::iter::repeat(0).take(len).collect::<Vec<_>>();
As told about in the blog post the first one will be able to be optimized via specializations to a single calloc call. The other here cannot use the same specialization as it does not seem to be able to specialize on the type of iterator yet. This means it will be a malloc followed by a memset when compiled.
godbolt: https://godbolt.org/z/8bM7zz4E7 https://godbolt.org/z/8bM7zz4E7
the specific specialization: https://github.com/rust-lang/rust/blob/master/library/alloc/src/vec/spec_from_elem.rs#L35..L48 https://github.com/rust-lang/rust/blob/master/library/alloc/...
- erk__ 5y agoDoing some further research you can make the optimized initialization of the WrappedByte vector by using it as a iterator. vec![0u8; len] .into_iter() .map(|x| WrappedByte(x)) .collect::<Vec<_>>() which will give you a list of WrappedBytes but initialized with calloc. I assume this is because llvm can see that the map is a identity function in this case and then can optimize it out. Godbolt: https://godbolt.org/z/hxnnPcjvG https://godbolt.org/z/hxnnPcjvG
- topspin 5y agoThat we might expect compilers to boil this statement down to calloc(n, s) is astonishing. The subtilty compilers is amazing.
- tialaramex 5y agoIf you write some of the "clever" pop count algorithms in C or C++, good compilers will go "Oh you're doing bit counting" and on a modern platform with a bit counting CPU instruction your whole algorithm turns into one CPU instruction. [In Rust the standard library provides count_ones() on integer types, and that's actually safely wrapping an intrinsic pop count feature]
- madmoose 5y agoC++ also has std::popcount since C++20. It should probably have had that from the beginning.
- the8472 5y agoIn this case it's a combination of compiler magic and specializations in the rust standard library to make it easy for the compiler to understand that this particular iterator shape is a NOP.