Arena
import { Arena } from "velt/mem". A typed memory pool (a region). Values are appended to one
growing array and named by their u32 index, and the whole pool is released at once with
reset(), which keeps the memory for the next round: a tree rebuilt on every iteration costs no
allocation after the first one.
It works best with small structs of numbers that link to each other by index
(struct Node { left: u32; right: u32 }), the shape of Rust's typed-arena programs: u32 indices
are half the size of pointers, so twice as many nodes fit in a cache line. Indices stay valid
until reset().
import { Arena } from "velt/mem";
struct Node {
left: u32;
right: u32;
}
const NONE: u32 = 4294967295;
function build(pool: Arena<Node>, depth: i64): u32 {
if (depth == 0) {
return pool.alloc(Node { left: NONE, right: NONE });
}
const l = build(pool, depth - 1);
const r = build(pool, depth - 1);
return pool.alloc(Node { left: l, right: r });
}
function count(pool: Arena<Node>, i: u32): i64 {
const n = pool.get(i);
return n.left == NONE ? 1 : 1 + count(pool, n.left) + count(pool, n.right);
}
const pool = new Arena<Node>(1024);
for (let round = 0; round < 3; round++) {
const root = build(pool, 6);
console.log(count(pool, root), pool.length); // 127 127
pool.reset();
}new Arena<T>(capacity: usize = 0):capacityvalues fit before the pool first grows.alloc(value): u32stores a value and returns its index.get(index): Treturns an independent copy;set(index, value)replaces the value.length: the values allocated since the lastreset().reset()drops every value and keeps the memory.
An index from before a reset() is out of bounds (a panic) until the pool grows past it again,
and then names whatever was allocated at that position: keep indices only as long as the round
that made them.