An index owns entries; an Executor owns the threads or streams a verb runs on; an Arena holds every output whose length scales with the call.
const usearch = @import("usearch");
var index = try usearch.DenseIndex.initRam(.{
.dimensions = 4,
.metric = .angular,
.quantization = .i8,
}, &.{}); // one shard per NUMA node, or the memory domains you name
defer index.deinit();
try index.reserve(1_000);
const keys = [_]usearch.Key{ .fromInteger(42), .fromInteger(43) };
const slab = [_]f32{ 0.2, 0.1, 0.2, 0.1, 0.1, 0.2, 0.1, 0.2 };
try index.insert(&keys, try .of(f32, &slab, 4), .{});
const query = [_]f32{ 0.2, 0.1, 0.2, 0.1 };
var arena = try usearch.Arena.init(null); // host pages, for calls on the calling thread
defer arena.deinit();
const matches = try index.search(try .of(f32, &query, 4), 10, &arena, .{}); // up to 10 matches per query
for ((try matches.query(0)).keys) |key| std.debug.print("{f}\n", .{key});
var executor = try usearch.Executor.forRam(.{});
defer executor.deinit();
_ = try index.on(executor).search(try .of(f32, &query, 4), 10, &arena, .{}); // the same verb, on an executor