oxc-project / backlog

backlog for collborators only
1 stars 0 forks source link

`ThinVec` type #113

Open overlookmotel opened 2 months ago

overlookmotel commented 2 months ago

The problem

There are various parts of AST where we have a Vec which is usually empty. e.g.:

To save space, we currently use Box<Vec<T>> for these fields. This is better than plain Vec, as it's 8 bytes instead of 32.

But downsides are:

  1. Checking if Vec is empty or not involves a "far off" memory read (follow Box's pointer).
  2. When the Vec does have content, reading/writing an element involves double-indirection (follow Box's pointer, then Vec'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. So ThinVec 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 cheap ThinVec::is_empty:

Optimization for single-entry ThinVecs

We could also have an optimization for ThinVecs with a single entry, where ThinVec would set lowest bit of pointer to 1 and the pointer points to the single entry (essentially it's a Box). 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 for Vecs which commonly contain only a single entry.

Dunqing commented 1 month 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?

Boshen commented 1 month ago

I don't think thin vec will have much effect given the number of usages is rare.