Change:
While landed a nice optimization of in , he said that it's still not performing as fast as doing a malloc and a . We should figure out why it is not performing as well as it should be and fix it in order to remove the temptation of using the faster unsafe functions.
It turns out this is substantially slower than I expected. With this test benchmark: I'm getting these results: This is related to and .
mentioned in irc that with the difference is: Which is much better, but still not great.
memset "cheats" with sse. fromelem spends a lot of time in moveval_init without optimizations so there's a bunch of unnecessary function calls. With optimizations, the thing that's killing it is the copies.
LLVM knows how to optimize loops to the same code as memcpy/memmove/memset though, as long as you generate good IR.
I a bench for the literal vec repeat syntax as well: Without optimizations: With optimizations (-O): Looking at the optimized IR, both setmemory and vecrepeat become a memset but setmemory seems to have a lot more overhead. does not become a memset hence the bad results.
this gets a lot better with the optimization passes from , from ~3x as slow to ~2x as slow Before (opt-level=2): After (opt-level=2)
the problem is with the code bloat from the surrounding code, rather than itself - I think we actually produce some IR there with undefined behaviour
greatly speeds up , fixing half of the issue Before: After:
The performance of all 3 has improved, but got slower relative to the others:
It looks like the remaining issue is our pointer arithmetic being slow. The and functions compile to conversions to and from integers, rather than actual pointer arithmetic with the stricter semantics. I think we need to make the and implementations for pointers a compiler feature.
Fixed by .
This since that fix, is attempting a bisect atm. Update: bisect finished, is to blame. isn't optimized. Maybe the needs to be inlined for further optimizations.
Note that set_memory has regressed by ~16ns, cause is ()

Discussion:
#[unsafe_destructor] impl<'a> Drop for Finallyalizer<'a> { <ins> #[inline] </ins> fn drop(&mut self) { (self.dtor)(); }

use vec; use vec::VectorVector; use option::*; <ins> use ptr; </ins> #[bench] fn iterator(bh: &mut BenchHarness) {

vec.contains(&99u); }) } <ins> #[bench] fn zero_1kb_from_elem(bh: &mut BenchHarness) { bh.iter(|| { let _v: ~[u8] = vec::from_elem(1024, 0u8); }); } #[bench] fn zero_1kb_set_memory(bh: &mut BenchHarness) { bh.iter(|| { let mut v: ~[u8] = vec::with_capacity(1024); unsafe { let vp = vec::raw::to_mut_ptr(v); ptr::set_memory(vp, 0, 1024); vec::raw::set_len(&mut v, 1024); } }); } #[bench] fn zero_1kb_fixed_repeat(bh: &mut BenchHarness) { bh.iter(|| { let _v: ~[u8] = ~[0u8, ..1024]; }); } #[bench] fn zero_1kb_loop_set(bh: &mut BenchHarness) { // Slower because the { len, cap, [0 x T] }* repr allows a pointer to the length // field to be aliased (in theory) and prevents LLVM from optimizing loads away. bh.iter(|| { let mut v: ~[u8] = vec::with_capacity(1024); unsafe { vec::raw::set_len(&mut v, 1024); } for i in range(0, 1024) { v[i] = 0; } }); } #[bench] fn zero_1kb_mut_iter(bh: &mut BenchHarness) { bh.iter(|| { let mut v: ~[u8] = vec::with_capacity(1024); unsafe { vec::raw::set_len(&mut v, 1024); } for x in v.mut_iter() { *x = 0; } }); } </ins> }