servo / rust-smallvec

"Small vector" optimization for Rust: store up to a small number of items on the stack
Apache License 2.0
1.32k stars 141 forks source link

u32 capacity and length? #257

Open leonardo-m opened 3 years ago

leonardo-m commented 3 years ago

This is an enhancement suggestion. Most times I want to use a SmallVec I don't need a huge number of cells, most times it's quite short. On the other hand saving some memory is often useful (an usage case of SmallVec for me is for 2D arrays of dynamic vectors, where most cells of the 2D matrix contain only very few items). So I think using a u32 for both capacity and length of the SmallVec could be enough (like in the Vec32 crate). It could be another cargo feature. Here SmallVec2 is a union of structs, both structs have fields in locked position (repr C), and both start with the capacity. This is less safe than the current design (of SmallVec1).

#![feature(untagged_unions)]
#![allow(dead_code)]

type Item = u8;
type Payload = [Item; 12];

union SmallVecData1 {
    inline: Payload,
    heap: (*mut Item, usize),
}

struct SmallVec1 {
    capacity: usize,
    data: SmallVecData1,
}

#[repr(C)]
#[derive(Copy, Clone)]
struct Inline {
    capacity: u32,
    data: Payload,
}

#[repr(C)]
struct Heap {
    capacity: u32,
    length: u32,
    ptr: *mut Item,
}

union SmallVec2 {
    inline: Inline,
    heap: Heap,
}

fn main() {
    println!("{}", std::mem::size_of::<SmallVec1>()); // 24
    println!("{}", std::mem::size_of::<SmallVec2>()); // 16
}
mbrubeck commented 3 years ago

arrayvec allows the index type to vary generically; this approach might be worth imitating.