On 04/04/14 10:51 AM, Manu Thambi wrote: > >> Needing to use a header seriously hurts the performance. The new >> vector is 7x faster at pushing elements when space isn't reserved >> compared to the old one, all due to leaving off the length/capacity >> header. The overhead would be less if it stored the capacity inside >> *and* outside the vector, but it's still overhead. It's an extra >> overflow check branch along with needing to calculate padding for >> alignment in the future, extra space in the memory allocation and more >> pointer aliasing issues. > Perhaps I am not understanding you correctly. Assuming that the capacity > is stored inside and outside Vec, the only overhead > I see is during allocation/deallocation. Otherwise the code will be > identical.
It bloats the code size by requiring extra overflow checks in functions like `push`, which impacts performance. Unwinding prevents many LLVM passes from doing their job, since it adds significant complexity to the control flow. In addition to this, there is even an impact on the performance of immutable operations like indexing. There's a need to calculate the offset to the first element in the vector, which includes compensating for alignment because there can be padding in between the capacity and the first element in the vector. You can deny that this has performance implications, but the fact is that I have looked at the performance and code size impact in depth and and have hard numbers from benchmarks proving that there is a enormous performance overhead for this choice. > If you are worried about space, there is a cost of > passing around Vecs ( vs ~[T]), which consumes and extra register for > the capacity. Passing vectors around by-value isn't a common operation. In the common case, functions operate on mutable or immutable borrowed slices. In uncommon cases, they operator on `&mut Vec<T>` in order to change the length in place. There are rare cases when ownership needs to be moved, but it's rare for it not to correspond by a constant factor to the number of allocations. >> It's going to be forbidden from actually being null in the future when >> the Option-like enum optimization is applied to it via an attribute. >> This work has already landed - calling exchange_free on a zero-size >> allocation is *forbidden*. > As mentioned elsewhere on this thread, we can use another invalid > pointer value to represent > either Option-None or 0 capacity depending on which is more efficient. I've already implemented support for this in the compiler some time ago and the library portion is now in master. This means it's invalid to call exchange_free on an allocation with a zero size capacity, so slices need to track whether the allocation is zero size. A zero size length does not imply a zero size capacity unless `Vec<T>` -> `~[T]` is not a no-op, which is what I am saying. Commits: 1778b6361627c5894bf75ffecf427573af02d390 898669c4e203ae91e2048fb6c0f8591c867bccc6
signature.asc
Description: OpenPGP digital signature
_______________________________________________ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev