Open overlookmotel opened 2 months ago
I'd like to learn and do it in my leisure time! Before that, I want to check with you and @Boshen, do we still need this currently?
I don't think thin vec will have much effect given the number of usages is rare.
The problem
There are various parts of AST where we have a
Vec
which is usually empty. e.g.:Function::directives
Class::decorators
FormalParameter::decorators
To save space, we currently use
Box<Vec<T>>
for these fields. This is better than plainVec
, as it's 8 bytes instead of 32.But downsides are:
Vec
is empty or not involves a "far off" memory read (followBox
's pointer).Vec
does have content, reading/writing an element involves double-indirection (followBox
's pointer, thenVec
's pointer).ThinVec
We could do a bit better with a
ThinVec
-like type.ThinVec
stores its length and capacity in same allocation as the vec's data. SoThinVec
itself is pointer-sized (8 bytes).I could not find an existing
ThinVec
-like crate which accepts a custom allocator, so we'd have to build our own.Designing for our use case
Because we'll be using it with arena allocator, we don't have to worry about
Drop
, so we could make a tweak to the design to allow very cheapThinVec::is_empty
:ThinVec
is empty (len == 0
), store a sentinel value in place of the pointer.0
.Option<ThinVec>
to also be pointer-sized, we could use aNonNull
pointer with sentinel value of1
. As long as alignment ofT
inThinVec<T>
is greater than 1 (all our AST types have alignment of at least 4), then1
can never be a valid pointer.ThinVec
has elements and has its last element removed, its pointer is replaced with the sentinel. This means its allocation is discarded, and if you push to theThinVec
again, it'll have to make a fresh allocation. But I think this is a rare case, so not much of a problem in practice.ThinVec::len
involves a branch to first check for the sentinel (rather than originalThinVec
where this is straight-line code). But as we expect almost allThinVec
s to be empty, this branch should be very predictable.Optimization for single-entry
ThinVec
sWe could also have an optimization for
ThinVec
s with a single entry, whereThinVec
would set lowest bit of pointer to1
and the pointer points to the single entry (essentially it's aBox
). This does impose cost of checking that bit and an AND instruction to get rid of it, on every read/write, so may not be worthwhile. But might be useful forVec
s which commonly contain only a single entry.