Thanks for the detailed reply. You clearly have done a lot of work on
the code,
and I have just been following the mailing lists for a while. So, I
might be misunderstanding something here.
On 04/04/2014 11:37 AM, Daniel Micay wrote:
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.
As Nathan mentioned, the capacity is stored at a negative offset to the
pointer to the heap.
So the Vec code should be identical, except that during
allocation/re-allocation, we need
to compute the heap pointer by adding sizeof(uint) to the value returned
by malloc().
(and the opposite computation on free())
indexing, etc, will not change, from how it is done now.
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.
I agree that passing around Vec by value is uncommon. But you seem to be
concerned about
Vec<T> -> ~[T] performance, which should also be a rare transfer of
ownership.
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
I understand that we cannot call free with a zero size/capacity.
There are three possibilities:
a) Use the special pointer value to represent Option::None. The Vec<T>
-> ~[T] would be a no-op.
b) If that makes implementation of Option complicated, then use the
special pointer value to represent
a zero capacity. We can use that special value in Vec<T> as well, even
though it is not needed. This
will keep Vec<T> -> ~[T] a no-op.
c) Conversion between Vec<T> -> ~[T] is not likely to be common. So,
doing an additional check is okay?
Thanks.
Manu
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev