23 ms·
if (vec.size < THRESHOLD) { vec.local[index] = value; } else { vec->heap[index] = value; }
by barrkel 9y ago
if (vec.size < THRESHOLD) { vec.local[index] = value; } else { vec->heap[index] = value; }
- mehrdadn 9y agoDidn't they say Vec is a (pointer, capacity, length) triplet though? Wouldn't it just be vec.pointer[index] = value regardless of whether the pointer points to the stack or the heap?
- barrkel 9y agopointer would be pointing at internal structure memory, it would need to change on every copy then.
- mehrdadn 9y ago> pointer would be pointing at internal structure memory, it would need to change on every copy then. Sure, sounds fine to me. What's wrong with this? The pointer would need to change on every copy anyway, since it'd need to point to a new buffer even if it were pointing to the heap.
- barrkel 9y agoIt sounds fine from a C++ world of copy constructors. I think copy constructors aren't worth the exception safety downsides.
- mehrdadn 9y agoI don't understand. I asked why there is a mandatory branch, you said otherwise the pointer would need to change on every copy, I said that's fine, and now you rebutted that copying isn't even worth it? So what is the problem and where is the extra branch? I don't understand where the discussion is going.
- koverstreet 9y agoYeah, that is the normal way of doing that optimization.
- kam 9y agoIn the "small vector optimization", the storage on the stack would be in place of the `(pointer, capacity, length)` except for a tag byte, so keeping the pointer would waste nearly 1/3 of the potential space. Also, when a Rust object is moved, there's no move constructor; it's purely a memory copy, so there would be no way to update the pointer for the new location.
- mehrdadn 9y ago> so keeping the pointer would waste nearly 1/3 of the potential space. Sure, but that still doesn't mean you'd get an extra branch? > Also, when a Rust object is moved, there's no move constructor; it's purely a memory copy, so there would be no way to update the pointer for the new location. Ah, this would seem like a complete deal-breaker. But if this is the case then why didn't they mention this instead of the other reasons? It seems far more compelling and fundamental than the other two? [EDIT: Ignore this last part. I think I confused the issue here with something else when adding this final sentence.] A̶l̶s̶o̶,̶ ̶t̶h̶i̶s̶ ̶̶s̶t̶i̶l̶l̶̶ ̶d̶o̶e̶s̶n̶'̶t̶ ̶m̶e̶a̶n̶ ̶t̶h̶e̶r̶e̶ ̶w̶o̶u̶l̶d̶ ̶b̶e̶ ̶a̶ ̶b̶r̶a̶n̶c̶h̶ ̶o̶n̶ ̶e̶v̶e̶r̶y̶ ̶a̶c̶c̶e̶s̶s̶,̶ ̶r̶i̶g̶h̶t̶?̶
- Manishearth 9y ago> Also, this still doesn't mean there would be a branch on every access, right? Yes it does, without a move constructor the only way to do a small vector optimization is to detect when the vector has been packed in the indexing operation and do the pointer math internal to the stack part of the vector. With move constructors you keep the pointer up to date, without them you have to recalculate this information on any kind of access, and for this you need to know when stuff must be recalculated which leads to the extra branch.