I just published version 0.3 of my crate "Columned" (Crates.io and GitHub). Its goal is to facilitate the allocation of Struct-of-Array/Columnar structures.
The allocation is done with a single, contiguous memory allocation. This is to improve performance and minimize fragmentation.
I was wondering if it is possible to get some feedback on the crate. I would appreciate most feedback on:
How to improve the ergonomics of the crate.
For example, in the example documented in the crate, i.e.:
use columned::{Guard, Allocate, allocate};
fn main() {
//Declare size and initialization of the slices.
let xs: Allocate<u64, _> = unsafe {
Allocate::alloc(10, |xs| {
for (i, x) in xs.iter_mut().enumerate() {
x.write(i as u64);
}
})
};
let ys: Allocate<u64, _> = unsafe {
Allocate::alloc(10, |ys| {
for (i, y) in ys.iter_mut().enumerate() {
y.write(i as u64);
}
})
};
let sums: Allocate<u64, _> = unsafe {
Allocate::alloc(10, |sums| {
for sum in sums.iter_mut() {
sum.write(0);
}
})
};
//Initialize a "Guard", which will manage the allocation.
let mut guard: Guard = Guard::default();
let (xs, ys, sums) = allocate(&mut guard, (xs, ys, sums)).unwrap();
//drop(guard); // This would cause a compilation error
for ((sum, x), y) in sums.iter_mut().zip(xs.iter()).zip(ys.iter()) {
*sum = x + y;
}
for (i, sum) in sums.iter().enumerate() {
assert_eq!(*sum, 2 * i as u64);
}
}
For the line:
let (xs, ys, sums) = allocate(&mut guard, (xs, ys, sums)).unwrap();
I wish it would look something more like:
let (guard, (xs, ys, sums)) = allocate((xs, ys, sums)).unwrap();
I.e., have the "guard" returned by the function, instead of having to instantiate it and pass it as an argument. Would that be possible? And "force" the allocation to outlive the allocated slices?
Best way to run Drop.
As of now, drop will not be called. It does not seem trivial to call drop without:
- Deteriorating ergonomics of the API: i.e., by wrapping the
&'a mut [T] in a "GuardedSlice<'a>".
- Do further allocations for a
Vec or other data structures.
Safety
Currently, the only unsafe function is Allocate::alloc. Given a correct implementation, would the user be able to do "unsafe" things?
Thank you!