Skip to content

Commit b446538

Browse files
author
john
committed
Expand QIHSE trinary search benchmark datasets
1 parent b87150a commit b446538

4 files changed

Lines changed: 67 additions & 20 deletions

File tree

plans/qihse_persistence_layer.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ Current landed state:
1414
- PR-3 read-only mmap candidate work now covers `vectors.qvec`, `metadata.qmeta`, validated `idmap.qid`, and validated direct mapping of `index.qidx` for clean snapshots.
1515
- PR-4 physical compaction is complete for the current row model: `compact()` rewrites the in-memory table, vector blob, and metadata arena with live rows only, then publishes the compact snapshot and regenerated `idmap.qid`/`vectors.qtri` through the existing atomic flush path.
1616
- PR-4 compaction fixtures now verify compact-after-mutation row/index/idmap/trinary behavior, high-ID idmap consistency, stale/corrupt derived sidecar rebuild, stale `.tmp` file ignore-on-open behavior, and WAL mutation compaction clearing WAL without resurrecting pruned rows.
17-
- PR-5 search-path benchmark scaffolding is present: `make bench-trinary-search-path` compares full float32 DB search against DB-backed `vectors.qtri` candidate selection plus exact float32 rerank and reports recall/order/latency. Pure trinary storage remains out of scope.
18-
- Latest pushed checkpoint before this slice: `b8a37a3` on `codex/qihse-file-persistence`.
17+
- PR-5 search-path benchmark scaffolding is present: `make bench-trinary-search-path` compares full float32 DB search against DB-backed `vectors.qtri` candidate selection plus exact float32 rerank across aligned, banded, and weighted deterministic datasets, reporting recall/order/latency for each. Pure trinary storage remains out of scope.
18+
- Latest pushed checkpoint before this slice: `b87150a` on `codex/qihse-file-persistence`.
1919

2020
Resume commands:
2121

@@ -46,14 +46,14 @@ Current continuation:
4646

4747
- PR-3: validate the newly landed `index.qidx` mmap path under more corruption and compatibility cases, then decide whether UMA should wrap mapped rows directly or keep the current vector DB-owned mapping path.
4848
- PR-4: add deeper manifest-publication crash fixtures if needed. Public mutation APIs, mutation WAL replay/truncation, physical compaction, stale temp-file handling coverage, and WAL-plus-compaction interaction coverage are present.
49-
- PR-5: use the search-path benchmark to drive optional vector DB trinary acceleration. Current benchmark proves recall/order on the synthetic fixture and exposes latency variance; it is not yet a production search-path optimization.
49+
- PR-5: use the search-path benchmark to drive optional vector DB trinary acceleration. Current benchmark proves recall/order on three deterministic fixtures and exposes latency variance; it is not yet a production search-path optimization.
5050
- PR-6: add persisted anchor hints and optimizer statistics only as rebuildable, explicit-format sidecars.
5151

5252
Recommended 3-agent split:
5353

5454
- Agent 1 owns any remaining manifest-publication crash fixtures.
5555
- Agent 2 owns PR-5 optional search-path acceleration wiring.
56-
- Agent 3 owns broader recall/performance datasets for trinary candidate generation.
56+
- Agent 3 owns additional realistic recall/performance datasets for trinary candidate generation.
5757

5858
## 1. Background
5959

plans/qihse_persistence_pr0_pr1_enhancement.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ Current implementation state:
3030
- PR-3 candidate work has started: read-only mmap mode maps `vectors.qvec`, `metadata.qmeta`, validated `idmap.qid`, and validated direct `index.qidx` rows for clean snapshots.
3131
- PR-4 physical compaction is present: delete/update/upsert API symbols write committed WAL records, replay committed mutation batches newer than the snapshot, writable open truncates torn/uncommitted mutation tails, and `compact()` rewrites live rows only before publishing the regenerated snapshot/sidecars.
3232
- PR-4 compaction fixture coverage now enforces row/index/live/idmap counts after physical pruning, high unsigned IDs, valid `vectors.qtri` after compact, stale/corrupt derived sidecar rebuild, stale `.tmp` file ignore-on-open behavior, and WAL mutation compaction clearing WAL without resurrecting pruned rows.
33-
- PR-5 search-path benchmark scaffolding is present: standalone tryte top-k exists with `make bench-trinary-codec`, DB-backed candidate generation plus exact float32 rerank exists with `make bench-trinary-db-candidate`, and `make bench-trinary-search-path` compares full float32 DB search against trinary candidates plus rerank with recall/order/latency reporting.
34-
- Latest pushed checkpoint before this slice: `b8a37a3` on `codex/qihse-file-persistence`.
33+
- PR-5 search-path benchmark scaffolding is present: standalone tryte top-k exists with `make bench-trinary-codec`, DB-backed candidate generation plus exact float32 rerank exists with `make bench-trinary-db-candidate`, and `make bench-trinary-search-path` compares full float32 DB search against trinary candidates plus rerank across aligned, banded, and weighted deterministic datasets with recall/order/latency reporting.
34+
- Latest pushed checkpoint before this slice: `b87150a` on `codex/qihse-file-persistence`.
3535
- `qihse/qihse_vector_db.c` was restored after a disk-full truncation and now contains the native persistence implementation.
3636
- `qihse_vector_db_create(..., db_path)` opens a file-backed native database.
3737
- `qihse_vector_db_open()` supports ephemeral, file-copy, read-only, and read-only mmap modes.
@@ -553,7 +553,7 @@ After the current checkpoint:
553553

554554
- PR-3: harden mmap compatibility and corruption tests now that read-only `vectors.qvec`, `metadata.qmeta`, `idmap.qid`, and `index.qidx` mapping are present for clean snapshots.
555555
- PR-4: public delete/update/upsert API behavior, mutation WAL replay/truncation, physical tombstone compaction, stale temp-file ignore behavior, and WAL-plus-compaction interactions are implemented and covered by persistence tests. Deeper manifest-publication crash fixtures can still be added.
556-
- PR-5: DB-backed candidate generation, exact rerank, and search-path benchmark scaffolding are present; production search-path acceleration, broader recall measurement, and optional pure trinary storage remain.
556+
- PR-5: DB-backed candidate generation, exact rerank, and three-dataset search-path benchmark scaffolding are present; production search-path acceleration, realistic recall measurement, and optional pure trinary storage remain.
557557
- PR-6: optional persisted anchor hints and optimizer statistics as rebuildable sidecars.
558558

559559
## PR-4: Mutation and Compaction Plan
@@ -719,7 +719,7 @@ Agent 2: PR-5 search-path trinary acceleration.
719719

720720
Agent 3: PR-5 recall/performance dataset expansion.
721721

722-
- Add broader recall/performance datasets beyond the synthetic fixture.
722+
- Add realistic recall/performance datasets beyond the deterministic aligned/banded/weighted fixtures.
723723
- Keep reporting speed honestly; the current benchmark proves recall/order but not consistent speedup.
724724
- Keep `vectors.qvec` authoritative until pure trinary storage has recovery, migration, and recall tests.
725725
- Update plan state after production search-path acceleration lands.

qihse/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ bench-trinary-search-path: lib
8585
benchmarks/qihse_trinary_db_candidate_bench.c \
8686
-L. -lqihse $(LDFLAGS)
8787
LD_LIBRARY_PATH=. /tmp/qihse_trinary_search_path_bench
88+
QIHSE_BENCH_DATASET=banded LD_LIBRARY_PATH=. /tmp/qihse_trinary_search_path_bench
89+
QIHSE_BENCH_DATASET=weighted LD_LIBRARY_PATH=. /tmp/qihse_trinary_search_path_bench
8890

8991
clean:
9092
rm -f *.o libqihse.so qihse_benchmark qihse_benchmark_a00 \

qihse/benchmarks/qihse_trinary_db_candidate_bench.c

Lines changed: 57 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@
1919
#define QIHSE_BENCH_TOPK 8u
2020
#define QIHSE_BENCH_ITERS 32u
2121

22+
typedef enum qihse_bench_dataset_e {
23+
QIHSE_BENCH_DATASET_ALIGNED = 0,
24+
QIHSE_BENCH_DATASET_BANDED = 1,
25+
QIHSE_BENCH_DATASET_WEIGHTED = 2
26+
} qihse_bench_dataset_t;
27+
2228
typedef struct qihse_bench_ranked_s {
2329
size_t row_index;
2430
uint64_t id;
@@ -43,41 +49,78 @@ static uint32_t qihse_bench_mix32(uint32_t value) {
4349
return value;
4450
}
4551

46-
static float qihse_bench_query_value(size_t dim) {
52+
static qihse_bench_dataset_t qihse_bench_dataset(void) {
53+
const char* name = getenv("QIHSE_BENCH_DATASET");
54+
55+
if (name && strcmp(name, "banded") == 0) {
56+
return QIHSE_BENCH_DATASET_BANDED;
57+
}
58+
if (name && strcmp(name, "weighted") == 0) {
59+
return QIHSE_BENCH_DATASET_WEIGHTED;
60+
}
61+
return QIHSE_BENCH_DATASET_ALIGNED;
62+
}
63+
64+
static const char* qihse_bench_dataset_name(qihse_bench_dataset_t dataset) {
65+
switch (dataset) {
66+
case QIHSE_BENCH_DATASET_BANDED:
67+
return "banded";
68+
case QIHSE_BENCH_DATASET_WEIGHTED:
69+
return "weighted";
70+
case QIHSE_BENCH_DATASET_ALIGNED:
71+
default:
72+
return "aligned";
73+
}
74+
}
75+
76+
static float qihse_bench_query_value(qihse_bench_dataset_t dataset, size_t dim) {
77+
if (dataset == QIHSE_BENCH_DATASET_BANDED) {
78+
return ((dim / 8u) % 2u == 0u) ? 1.0f : -1.0f;
79+
}
80+
if (dataset == QIHSE_BENCH_DATASET_WEIGHTED) {
81+
return (dim % 5u == 0u || dim % 5u == 1u) ? 1.0f : -1.0f;
82+
}
4783
return (dim % 3u == 0u) ? 1.0f : -1.0f;
4884
}
4985

5086
static void qihse_bench_fill_data(float* rows, float* query, uint64_t* ids) {
87+
qihse_bench_dataset_t dataset = qihse_bench_dataset();
5188
size_t row;
5289
size_t dim;
5390

5491
for (dim = 0u; dim < QIHSE_BENCH_DIMS; dim++) {
55-
query[dim] = qihse_bench_query_value(dim);
92+
query[dim] = qihse_bench_query_value(dataset, dim);
5693
}
5794

5895
for (row = 0u; row < QIHSE_BENCH_ROWS; row++) {
59-
ids[row] = 100000u + (uint64_t)row;
96+
ids[row] = 100000u + ((uint64_t)dataset * 1000000u) + (uint64_t)row;
6097
for (dim = 0u; dim < QIHSE_BENCH_DIMS; dim++) {
6198
uint32_t mixed = qihse_bench_mix32((uint32_t)((row + 17u) * 131u +
62-
(dim + 5u) * 977u));
63-
uint32_t bucket = mixed % 5u;
99+
(dim + 5u) * 977u +
100+
((uint32_t)dataset * 65537u)));
101+
uint32_t bucket = mixed % (dataset == QIHSE_BENCH_DATASET_ALIGNED ? 5u : 7u);
64102
float value = 0.0f;
65103

66-
if (bucket == 0u || bucket == 1u) {
104+
if (bucket == 0u || bucket == 1u ||
105+
(dataset == QIHSE_BENCH_DATASET_WEIGHTED && bucket == 2u)) {
67106
value = query[dim];
68-
} else if (bucket == 2u || bucket == 3u) {
107+
} else if (bucket == 2u || bucket == 3u || bucket == 4u) {
69108
value = -query[dim];
70109
}
110+
if (dataset == QIHSE_BENCH_DATASET_WEIGHTED && value != 0.0f) {
111+
value *= (dim % 7u == 0u) ? 2.0f : 0.75f;
112+
}
71113
rows[(row * QIHSE_BENCH_DIMS) + dim] = value;
72114
}
73115
}
74116

75117
for (dim = 0u; dim < QIHSE_BENCH_DIMS; dim++) {
76-
rows[dim] = query[dim];
77-
rows[QIHSE_BENCH_DIMS + dim] = dim == 7u ? 0.0f : query[dim];
78-
rows[(2u * QIHSE_BENCH_DIMS) + dim] = dim == 11u ? -query[dim] : query[dim];
118+
float scale = dataset == QIHSE_BENCH_DATASET_WEIGHTED && dim % 7u == 0u ? 2.0f : 1.0f;
119+
rows[dim] = query[dim] * scale;
120+
rows[QIHSE_BENCH_DIMS + dim] = dim == 7u ? 0.0f : query[dim] * scale;
121+
rows[(2u * QIHSE_BENCH_DIMS) + dim] = dim == 11u ? -query[dim] : query[dim] * scale;
79122
rows[(3u * QIHSE_BENCH_DIMS) + dim] =
80-
(dim == 13u || dim == 17u) ? -query[dim] : query[dim];
123+
(dim == 13u || dim == 17u) ? -query[dim] : query[dim] * scale;
81124
}
82125
}
83126

@@ -416,6 +459,7 @@ static int32_t qihse_bench_candidate_score_for_row(const size_t* candidate_rows,
416459
}
417460

418461
int main(void) {
462+
qihse_bench_dataset_t dataset = qihse_bench_dataset();
419463
char* db_path = NULL;
420464
qihse_vector_db_t full_db = NULL;
421465
float* rows = NULL;
@@ -588,8 +632,9 @@ int main(void) {
588632
full_results,
589633
full_topk_count);
590634

591-
printf("trinary_search_path_bench rows=%u dims=%u qtri_row_bytes=%zu "
635+
printf("trinary_search_path_bench dataset=%s rows=%u dims=%u qtri_row_bytes=%zu "
592636
"candidates=%u topk=%u iterations=%u\n",
637+
qihse_bench_dataset_name(dataset),
593638
(unsigned)QIHSE_BENCH_ROWS,
594639
(unsigned)QIHSE_BENCH_DIMS,
595640
row_bytes,

0 commit comments

Comments
 (0)