use super::enumeration::{enumerate_page, scrambled_store};
use super::*;
const SWEEP_SIZES: [u64; 4] = [250, 500, 1000, 2000];
fn seeded_at_size(n: u64) -> tempfile::TempDir {
let dir = tempfile::tempdir().expect("tempdir");
{
let store = NativeStore::open(dir.path(), DIM).expect("open");
for id in 1..=n {
store
.store_with_metadata(
id * 7,
&format!("fact {id}"),
&EMBEDDING,
&meta(&[("project", Value::from("veles"))]),
)
.expect("seed");
}
}
dir
}
fn per_fact(elapsed: std::time::Duration, n: u64) -> f64 {
let micros = u32::try_from(elapsed.as_micros()).map_or(f64::from(u32::MAX), f64::from);
micros / f64::from(u32::try_from(n).expect("fits"))
}
fn bench_points(n: u64) -> Vec<velesdb_core::Point> {
(1..=n)
.map(|id| {
let payload = serde_json::json!({
"content": format!("fact {id}"),
"project": "veles",
});
velesdb_core::Point::new(id, EMBEDDING.to_vec(), Some(payload))
})
.collect()
}
fn empty_store() -> tempfile::TempDir {
let dir = tempfile::tempdir().expect("tempdir");
drop(NativeStore::open(dir.path(), DIM).expect("open store"));
dir
}
fn time_batched(
points: &[velesdb_core::Point],
batch: usize,
bulk: bool,
) -> (std::time::Duration, usize, usize) {
let dir = empty_store();
let db = database(&dir);
let coll = db
.get_vector_collection("_semantic_memory")
.expect("collection exists");
let start = std::time::Instant::now();
let mut calls = 0usize;
for chunk in points.chunks(batch) {
if bulk {
coll.upsert_bulk(chunk).expect("bulk upsert");
} else {
coll.upsert(chunk.to_vec()).expect("upsert");
}
calls += 1;
}
let elapsed = start.elapsed();
let read_back = super::enumerate_by_cursor(&db, "_semantic_memory", 4_096)
.expect("read back")
.len();
(elapsed, calls, read_back)
}
fn time_unit(n: u64) -> std::time::Duration {
let dir = tempfile::tempdir().expect("tempdir");
let start = std::time::Instant::now();
{
let store = NativeStore::open(dir.path(), DIM).expect("open");
for id in 1..=n {
store
.store_with_metadata(
id,
&format!("fact {id}"),
&EMBEDDING,
&meta(&[("project", Value::from("veles"))]),
)
.expect("seed");
}
}
start.elapsed()
}
fn distinct_vector(id: u64, dim: usize) -> Vec<f32> {
let mut state = id.wrapping_mul(6_364_136_223_846_793_005).wrapping_add(1);
let mut out = Vec::with_capacity(dim);
for _ in 0..dim {
state = state
.wrapping_mul(6_364_136_223_846_793_005)
.wrapping_add(1_442_695_040_888_963_407);
let bits = u32::try_from(state >> 32).expect("shifted into 32 bits");
out.push(f32::from_bits((bits >> 9) | 0x3f80_0000) - 1.5);
}
out
}
type PayloadShape = fn(u64) -> Option<Value>;
fn varied_points(n: u64, dim: usize) -> Vec<velesdb_core::Point> {
(1..=n)
.map(|id| {
let payload = serde_json::json!({
"content": format!("fact {id}"),
"project": "veles",
});
velesdb_core::Point::new(id, distinct_vector(id, dim), Some(payload))
})
.collect()
}
#[test]
#[ignore = "writes 2 000 facts twice; run deliberately, on a machine at rest"]
fn the_per_point_write_cost_is_measured_against_varied_vectors() {
const N: u64 = 2_000;
const BATCH: usize = 1_024;
let expected = usize::try_from(N).expect("fits");
let (flat, _, flat_read) = time_batched(&bench_points(N), BATCH, true);
assert_eq!(
flat_read, expected,
"identical-vector write must be readable"
);
let (varied, _, varied_read) = time_batched(&varied_points(N, DIM), BATCH, true);
assert_eq!(
varied_read, expected,
"varied-vector write must be readable"
);
println!(
" identical vectors {flat:>10.2?} {:>9.1} us/fact",
per_fact(flat, N)
);
println!(
" distinct vectors {varied:>10.2?} {:>9.1} us/fact",
per_fact(varied, N)
);
println!(
" ratio identical/distinct = {:.2}",
per_fact(flat, N) / per_fact(varied, N)
);
}
#[test]
#[ignore = "writes 2 000 facts three times; run deliberately, on a machine at rest"]
fn the_per_point_write_cost_is_attributed_to_payload_or_vector() {
const N: u64 = 2_000;
const BATCH: usize = 1_024;
let expected = usize::try_from(N).expect("fits");
let shapes: [(&str, PayloadShape); 4] = [
("full (content+project)", |id| {
Some(serde_json::json!({ "content": format!("fact {id}"), "project": "veles" }))
}),
("no content key (still text)", |_| {
Some(serde_json::json!({ "project": "veles" }))
}),
("numeric only (no text)", |id| {
Some(serde_json::json!({ "n": id }))
}),
("no payload at all", |_| None),
];
for (label, shape) in shapes {
let points: Vec<velesdb_core::Point> = (1..=N)
.map(|id| velesdb_core::Point::new(id, distinct_vector(id, DIM), shape(id)))
.collect();
let (elapsed, _, read_back) = time_batched(&points, BATCH, true);
assert_eq!(
read_back, expected,
"the write must stay readable for shape `{label}`"
);
println!(
" {label:<24} {elapsed:>10.2?} {:>9.1} us/fact",
per_fact(elapsed, N)
);
}
}
#[test]
#[ignore = "writes 31 000 facts; run deliberately, on a machine at rest"]
fn batched_write_cost_stays_flat_as_the_volume_doubles() {
const BATCH: usize = 1_024;
let mut measured: Vec<(u64, f64)> = Vec::new();
for n in [1_000u64, 2_000, 4_000, 8_000, 16_000] {
let (elapsed, calls, read_back) = time_batched(&varied_points(n, DIM), BATCH, true);
assert_eq!(
read_back,
usize::try_from(n).expect("fits"),
"the batched write must be readable in full at n={n}"
);
let cost = per_fact(elapsed, n);
let ratio = measured.last().map_or(String::from("—"), |(_, prev)| {
format!("x{:.2}", cost / prev)
});
println!(
" n={n:6} {elapsed:>10.2?} {cost:>9.1} us/fact {:>8.0} facts/s calls={calls:<4} ratio={ratio}",
1_000_000.0 / cost
);
measured.push((n, cost));
}
let first = measured.first().expect("measured").1;
let last = measured.last().expect("measured").1;
println!(" per-fact cost {first:.1} -> {last:.1} us/fact across a 16x volume increase");
assert!(
last < first * 2.0,
"a 16x volume must not double the PER-FACT cost, or the rebuild does not \
scale: {first:.1} -> {last:.1} us/fact. Quadratic growth here means \
`scalable_reconstruction` is Missing and PR B does not start."
);
}
#[test]
#[ignore = "writes 2 000 facts per configuration; run deliberately, on a machine at rest"]
fn write_path_unit_versus_batch_at_a_fixed_volume() {
const N: u64 = 2_000;
let unit = time_unit(N);
println!(
" store_with_metadata (unit) {unit:>12.2?} {:>9.1} us/fact calls={N}",
per_fact(unit, N)
);
let points = bench_points(N);
let mut best = (usize::MAX, f64::MAX, false);
for batch in [1usize, 16, 64, 256, 1_024, 4_096] {
for bulk in [false, true] {
let (elapsed, calls, read_back) = time_batched(&points, batch, bulk);
assert_eq!(
read_back,
usize::try_from(N).expect("fits"),
"the write must be READABLE afterwards: batch={batch} bulk={bulk} \
wrote {read_back} of {N}"
);
let cost = per_fact(elapsed, N);
let label = if bulk { "upsert_bulk" } else { "upsert " };
println!(
" {label} batch={batch:<5} {elapsed:>12.2?} {cost:>9.1} us/fact calls={calls}"
);
if cost < best.1 {
best = (batch, cost, bulk);
}
}
}
let unit_cost = per_fact(unit, N);
println!(
" BEST: {} at batch={} -> {:.1} us/fact ({:.1}x the unit path)",
if best.2 { "upsert_bulk" } else { "upsert" },
best.0,
best.1,
unit_cost / best.1
);
assert!(
best.1 < unit_cost,
"batching must beat the per-fact path or a rebuild has no batched route: \
best {:.1} us/fact vs unit {unit_cost:.1} us/fact",
best.1
);
}
#[test]
#[ignore = "seeds thousands of facts; run deliberately, on a machine at rest"]
fn paging_cost_grows_faster_than_the_store() {
let mut costs: Vec<f64> = Vec::new();
for n in SWEEP_SIZES {
let dir = seeded_at_size(n);
let db = database(&dir);
let start = std::time::Instant::now();
let facts = enumerate_collection(&db, "_semantic_memory", 100).expect("enumerate");
let elapsed = start.elapsed();
assert_eq!(facts.len(), usize::try_from(n).expect("fits"));
let cost = per_fact(elapsed, n);
println!(" n={n:5} elapsed={elapsed:>9.2?} us/fact={cost:>7.1}");
costs.push(cost);
}
let first = costs.first().copied().expect("measured");
let last = costs.last().copied().expect("measured");
assert!(
last > first * 1.5,
"the per-fact cost was expected to RISE with the volume (it is what makes this walk unusable at scale); if it no longer does, the engine gained a cheaper scan and this capability should be re-classified — first={first:.1} us/fact, last={last:.1} us/fact"
);
}
#[test]
#[ignore = "seeds thousands of facts; run deliberately, on a machine at rest"]
fn the_cursor_cost_per_fact_does_not_grow_like_the_offset_walk() {
let mut cursor_costs: Vec<f64> = Vec::new();
let mut offset_costs: Vec<f64> = Vec::new();
for n in SWEEP_SIZES {
let dir = seeded_at_size(n);
let db = database(&dir);
let expected = usize::try_from(n).expect("fits");
let start = std::time::Instant::now();
let walked = super::enumerate_by_cursor(&db, "_semantic_memory", 100).expect("cursor walk");
let cursor_elapsed = start.elapsed();
assert_eq!(
walked.len(),
expected,
"positive control: a cursor walk that returned the wrong count would \
make its timing meaningless"
);
let start = std::time::Instant::now();
let paged = enumerate_collection(&db, "_semantic_memory", 100).expect("page walk");
let offset_elapsed = start.elapsed();
assert_eq!(paged.len(), expected, "positive control for the page walk");
let (cursor, offset) = (per_fact(cursor_elapsed, n), per_fact(offset_elapsed, n));
println!(
" n={n:5} cursor={cursor_elapsed:>9.2?} ({cursor:>7.1} us/fact) \
offset={offset_elapsed:>9.2?} ({offset:>7.1} us/fact)"
);
cursor_costs.push(cursor);
offset_costs.push(offset);
}
let growth = |costs: &[f64]| -> f64 {
let first = costs.first().copied().expect("measured");
let last = costs.last().copied().expect("measured");
last / first
};
let (cursor_growth, offset_growth) = (growth(&cursor_costs), growth(&offset_costs));
println!(
" per-fact cost grew x{cursor_growth:.2} for the cursor, \
x{offset_growth:.2} for the offset walk, over an 8x volume"
);
assert!(
cursor_growth <= offset_growth,
"the cursor's per-fact cost grew at least as fast as the OFFSET walk's \
(cursor x{cursor_growth:.2}, offset x{offset_growth:.2}). The rebuild is \
built on the cursor precisely because the other walk is quadratic; if \
they now degrade alike, that premise no longer holds and the choice has \
to be re-argued rather than inherited"
);
}
#[test]
#[cfg(feature = "embedder-http")]
#[ignore = "needs a live embedding backend; run deliberately, on a machine at rest"]
fn the_embedder_dominates_only_when_the_model_changes() {
use crate::embedder::{Embedder, OllamaEmbedder};
const FACTS: usize = 32;
let n = u64::try_from(FACTS).expect("fits");
let texts: Vec<String> = (0..FACTS)
.map(|i| format!("fact number {i}: what a rebuild has to carry across"))
.collect();
let url = std::env::var("VELESDB_MEMORY_OLLAMA_URL")
.unwrap_or_else(|_| "http://localhost:11434".to_owned());
let model =
std::env::var("VELESDB_MEMORY_OLLAMA_MODEL").unwrap_or_else(|_| "bge-m3".to_owned());
let embedder = OllamaEmbedder::new(&url, &model).unwrap_or_else(|e| {
panic!(
"this test measures a REAL embedder and {url} / {model} is unreachable ({e}); \
it must fail here rather than report a cost for a backend that is not there"
)
});
let dimension = embedder.dimension();
embedder.embed("warm up").expect("warm up");
let start = std::time::Instant::now();
let vectors: Vec<Vec<f32>> = texts
.iter()
.map(|text| embedder.embed(text).expect("embed"))
.collect();
let embed_elapsed = start.elapsed();
let batch: Vec<(RawFact, Vec<f32>)> = vectors
.into_iter()
.enumerate()
.map(|(i, vector)| {
let id = u64::try_from(i).expect("fits") + 1;
let payload = serde_json::json!({ "content": texts[i] }).to_string();
let source_vector = vector.clone();
(
RawFact {
id,
payload,
source_vector,
},
vector,
)
})
.collect();
let dir = tempfile::tempdir().expect("tempdir");
{
let _store = NativeStore::open(dir.path(), dimension).expect("open destination");
}
let db = database(&dir);
let start = std::time::Instant::now();
let written = reinsert_batch(&db, "_semantic_memory", &batch).expect("reinsert");
let reinsert_elapsed = start.elapsed();
assert_eq!(
written.inserted, n,
"positive control: a batch that did not land would make its timing meaningless"
);
let embed_cost = per_fact(embed_elapsed, n);
let reinsert_cost = per_fact(reinsert_elapsed, n);
println!(" model={model} dimension={dimension} facts={FACTS}");
println!(
" re-embedding (model CHANGED): {embed_elapsed:>10.2?} {embed_cost:>10.1} us/fact"
);
println!(" reinsertion (vectors REUSED): {reinsert_elapsed:>10.2?} {reinsert_cost:>10.1} us/fact");
println!(
" embedding costs x{:.0} what reinsertion costs, per fact",
embed_cost / reinsert_cost
);
assert!(
embed_cost > reinsert_cost,
"re-embedding was not more expensive than reinsertion (embed \
{embed_cost:.1} us/fact, reinsert {reinsert_cost:.1} us/fact). The whole \
reason a rebuild reuses source vectors when the model is unchanged is \
that it is not; if that stops holding, the choice has to be re-argued \
rather than inherited"
);
}
#[test]
fn the_cursor_walk_matches_the_page_walk_fact_for_fact() {
let (dir, expected, _count) = scrambled_store();
let db = database(&dir);
let by_page = enumerate_collection(&db, "_semantic_memory", PAGE).expect("page walk");
let by_cursor = super::enumerate_by_cursor(&db, "_semantic_memory", PAGE).expect("cursor walk");
let cursor_ids: BTreeSet<u64> = by_cursor.iter().map(|f| f.id).collect();
assert_eq!(
by_cursor.len(),
cursor_ids.len(),
"the cursor walk returned a fact twice: {:?}",
by_cursor.iter().map(|f| f.id).collect::<Vec<_>>()
);
assert_eq!(
cursor_ids, expected,
"the cursor walk must cover exactly the seeded ids"
);
let mut page_sorted = by_page;
page_sorted.sort_by_key(|f| f.id);
let mut cursor_sorted = by_cursor;
cursor_sorted.sort_by_key(|f| f.id);
for (page, cursor) in page_sorted.iter().zip(cursor_sorted.iter()) {
let page_json: Value = serde_json::from_str(&page.payload).expect("page payload is json");
let cursor_json: Value =
serde_json::from_str(&cursor.payload).expect("cursor payload is json");
assert_eq!(
page_json, cursor_json,
"the two paths disagree on the payload of fact {}",
page.id
);
}
}
#[test]
fn a_cursor_resumed_mid_walk_skips_nothing_and_repeats_nothing() {
let (dir, expected, _count) = scrambled_store();
let db = database(&dir);
let (head, cursor) = super::scroll_page(&db, "_semantic_memory", None, 3).expect("first batch");
let mut seen: Vec<u64> = head.iter().map(|f| f.id).collect();
let mut next = cursor;
while let Some(from) = next {
let (batch, after) =
super::scroll_page(&db, "_semantic_memory", Some(from), 3).expect("resumed batch");
if batch.is_empty() {
break;
}
seen.extend(batch.iter().map(|f| f.id));
next = after;
}
let unique: BTreeSet<u64> = seen.iter().copied().collect();
assert_eq!(seen.len(), unique.len(), "resume duplicated ids: {seen:?}");
assert_eq!(
unique, expected,
"a walk resumed from a recorded cursor must cover exactly the same set"
);
let ascending: Vec<u64> = expected.iter().copied().collect();
assert_eq!(
seen, ascending,
"scroll_batch documents ascending id order; the rebuild's checkpointing \
depends on it"
);
}
const OFFSET_CEILING: u64 = 100_000;
const SEEDED_ABOVE_CEILING: u64 = OFFSET_CEILING + 1;
const CEILING_PAGE: usize = 10;
fn seed_store_above_offset_ceiling() -> tempfile::TempDir {
let dir = tempfile::tempdir().expect("tempdir");
let seed_start = std::time::Instant::now();
{
let store = NativeStore::open(dir.path(), DIM).expect("open");
for id in 1..=SEEDED_ABOVE_CEILING {
store
.store_with_metadata(
id,
&format!("fact {id}"),
&EMBEDDING,
&meta(&[("project", Value::from("veles"))]),
)
.expect("seed");
}
}
println!(
" seeded {SEEDED_ABOVE_CEILING} facts in {:?}",
seed_start.elapsed()
);
dir
}
fn assert_offset_walk_stops_at_ceiling(db: &velesdb_core::Database) {
let straddling = enumerate_page(
db,
"_semantic_memory",
CEILING_PAGE,
usize::try_from(OFFSET_CEILING - 5).expect("fits"),
);
let past = enumerate_page(
db,
"_semantic_memory",
CEILING_PAGE,
usize::try_from(OFFSET_CEILING).expect("fits"),
);
println!(
" OFFSET page at {} -> {} rows (asked {CEILING_PAGE})",
OFFSET_CEILING - 5,
straddling.len()
);
println!(
" OFFSET page at {OFFSET_CEILING} -> {} rows (fact {SEEDED_ABOVE_CEILING} exists)",
past.len()
);
assert!(
straddling.len() < CEILING_PAGE,
"expected the cap to SHORTEN a straddling page; it returned a full page \
of {}, so the executor no longer clamps `limit + offset`",
straddling.len()
);
assert!(
past.is_empty(),
"expected the cap to EMPTY a page at the ceiling; it returned {} rows",
past.len()
);
}
fn assert_cursor_crosses_offset_ceiling(db: &velesdb_core::Database) {
let cursor_start = std::time::Instant::now();
let by_cursor =
super::enumerate_by_cursor(db, "_semantic_memory", 10_000).expect("cursor enumeration");
let cursor_elapsed = cursor_start.elapsed();
let ids: BTreeSet<u64> = by_cursor.iter().map(|f| f.id).collect();
println!(
" CURSOR walk -> {} rows in {cursor_elapsed:?} ({:.1} us/fact)",
by_cursor.len(),
per_fact(cursor_elapsed, SEEDED_ABOVE_CEILING)
);
assert_eq!(
by_cursor.len(),
ids.len(),
"the cursor walk returned a fact twice"
);
assert_eq!(
ids.len(),
usize::try_from(SEEDED_ABOVE_CEILING).expect("fits"),
"the cursor walk must reach EVERY fact past the cap that bounds the \
OFFSET walk; it stopped at {} of {SEEDED_ABOVE_CEILING}",
ids.len()
);
assert!(
ids.contains(&SEEDED_ABOVE_CEILING),
"the fact beyond the cap is precisely the one the OFFSET walk drops; the \
cursor must carry it"
);
}
#[test]
#[ignore = "seeds 100_001 facts; run deliberately, on a machine at rest"]
fn past_the_ceiling_the_offset_walk_truncates_and_the_cursor_does_not() {
let dir = seed_store_above_offset_ceiling();
let db = database(&dir);
assert_offset_walk_stops_at_ceiling(&db);
assert_cursor_crosses_offset_ceiling(&db);
}