Validate shared-engine lexical performance harness on Windows
This commit is contained in:
1 parent
fb8b45dcc9
commit
4e277a107f
6 files changed
+1534
No files matched your search
@@ -0,0 +1,121 @@
|
||||
# Large-index lexical performance protocol
|
||||
|
||||
Status: **1,000-record smoke executed; large run deferred**. No production
|
||||
release gate is passed by this document.
|
||||
|
||||
`tools/scale-eval` uses the actual shared Rust `SearchIndex` engine, with no
|
||||
desktop, model worker or semantic inference. The intended scale is **1 million
|
||||
file records and 100,000 text documents**, with 100 measured requests per case
|
||||
and mode. A 1,000-record smoke run must pass first.
|
||||
|
||||
## What the fixture represents
|
||||
|
||||
The engine opens and migrates the database before bounded 1,000-row transactions
|
||||
insert synthetic metadata and one short passage per text document. Existing
|
||||
engine triggers populate filename trigram, full-text and passage indexes; all
|
||||
four FTS tables receive integrity checks, followed by SQLite
|
||||
integrity checking. No FTS schema or engine retrieval API is replaced.
|
||||
The intentionally sparse `content_search` receives internal integrity checking;
|
||||
the other three additionally compare external content. Requiring every empty
|
||||
file row in the sparse index would falsely report corruption.
|
||||
|
||||
Only two empty directories are created so production folder canonicalization
|
||||
and component-boundary filtering operate normally. The neighboring directories
|
||||
`chosen` and `chosen-other` test accidental prefix inclusion. No million-file
|
||||
filesystem corpus is created. Text/code records alternate extensions; a filtered
|
||||
common-term query combines folder, extension, code, size and modification time.
|
||||
Every request checks positive/absent outcomes; exact filenames must retain first
|
||||
place and unique content markers must identify their corresponding document.
|
||||
|
||||
This bypasses discovery, permissions, extraction, hashing source input, watcher
|
||||
traffic and real source access. Synthetic records have no verified extraction
|
||||
provenance and must never be used for semantic indexing or agent excerpts.
|
||||
Short repeated text and similarly shaped names are deliberately reproducible
|
||||
workloads, not a representative customer library. The database SHA identifies
|
||||
the actual run; absolute temporary-root bytes make it machine/run dependent.
|
||||
The fixed seed and record-generation algorithm identify the logical dataset.
|
||||
|
||||
## Run and preserve evidence
|
||||
|
||||
From the repository root, once no other performance/inference task owns CPU:
|
||||
|
||||
```powershell
|
||||
$env:SEARCHI_FORCE_CPU = '1'
|
||||
cargo build --release --manifest-path tools/scale-eval/Cargo.toml --locked -j 1
|
||||
tools/scale-eval/target/release/searchi-scale-eval.exe 1000 100 20 .searchi/qa/scale-smoke.json
|
||||
tools/scale-eval/target/release/searchi-scale-eval.exe 1000000 100000 100 .searchi/qa/scale-million.json
|
||||
python tools/scale-eval/summarize.py .searchi/qa/scale-million.json
|
||||
```
|
||||
|
||||
Linux/macOS use the same binary path without `.exe`. Build once, then retain
|
||||
the committed diagnostic `Cargo.lock` and its SHA alongside evidence; this
|
||||
standalone diagnostic intentionally has its own dependency lock and is outside
|
||||
the product workspace. Reports use `create_new`, refusing to overwrite earlier samples.
|
||||
The owned temporary database is removed automatically; callers' directories
|
||||
are never recursively deleted. A forcibly killed process may leave its owned
|
||||
`searchi-scale-*` directory, which should be inspected before explicit cleanup.
|
||||
|
||||
Record source commit, clean/dirty status, compiler (`rustc -Vv`), dependency lock
|
||||
SHA, CPU model, VM/physical status, RAM, storage, OS version, power mode and any
|
||||
competing jobs. Report embeds executable SHA, OS/architecture/logical CPUs,
|
||||
schema version, database SHA/size and seed time. SQLite queries run synchronously
|
||||
on one caller thread; logical CPU count does not describe a bounded whole-app
|
||||
resource budget. Monitor peak memory/storage externally during the large run.
|
||||
|
||||
## Distinct measurements
|
||||
|
||||
- Reader open, first unprepared input and background `prewarm` are separate.
|
||||
- Per-case first input after production prewarm precedes that case's repeated
|
||||
measurements. Prewarm itself searches representative names/content; this is
|
||||
not a wholly unseen cold query.
|
||||
- Warm exact/unique requests vary deterministic IDs; common name/keyword,
|
||||
strict filters and absent queries repeat. Basic/Debug are paired AB/BA to
|
||||
reduce order bias. Each mode retains every wall-clock sample and actual engine
|
||||
metrics. Debug retains full bounded traces; their nested durations are not
|
||||
summed. Result assertions run after measured retrieval and outside wall time.
|
||||
- Reopened-reader open and first keyword request are separate after warm tests.
|
||||
These **do not flush OS/SQLite storage caches** and are not cold-storage tests.
|
||||
- `summarize.py` uses nearest-rank p50/p95 and retains negative paired overhead
|
||||
caused by measurement noise. It never emits a production pass verdict.
|
||||
- The recorded exact-lookup SQL plan is a narrow schema diagnostic, not evidence
|
||||
that every dynamic production retrieval lane uses that plan. Inspect actual
|
||||
debug lane timings/candidate counters when investigating regressions.
|
||||
|
||||
UI input/paint, semantic inference/ANN, concurrent indexing, long documents,
|
||||
Unicode-heavy names, skewed customer content, network/removable storage,
|
||||
filesystem lifecycle and cold-machine tests remain separate release gates.
|
||||
The original 50 ms filename and 150 ms keyword p95 goals may be compared with
|
||||
these samples, but reaching them here proves only this synthetic lexical case.
|
||||
|
||||
## Windows VM smoke, 2026-10-13
|
||||
|
||||
Actual optimized shared-engine run: 1,000 metadata records, 100 short text
|
||||
documents, 20 paired samples per mode per case. All expected identities,
|
||||
combined filters and absent outcomes passed. No inference or GPU was used;
|
||||
the installed desktop remained running, so these are not isolated performance
|
||||
measurements. Rust 1.99.0, x86_64-pc-windows-msvc.
|
||||
|
||||
| Case | Basic warm p95 (ms) | Debug warm p95 (ms) |
|
||||
| --- | --- | --- |
|
||||
| Exact filename | 0.8893 | 1.3266 |
|
||||
| Unique keyword | 1.3823 | 2.2248 |
|
||||
| Common keyword | 1.3285 | 1.4759 |
|
||||
| Common filename | 0.6131 | 0.6961 |
|
||||
| Combined filters | 0.9019 | 1.1783 |
|
||||
| Absent keyword | 0.4442 | 0.6847 |
|
||||
|
||||
Reader open: 4.6814 ms; prewarm: 62.4835 ms; reopened reader: 3.1992 ms.
|
||||
Raw ignored evidence `.searchi/qa/scale-smoke-20261013.json`, SHA-256
|
||||
`79f58066f8e42ee3c249eeb341a8ce934b619e3c308038081845c8d24a4543de`.
|
||||
Executable SHA-256
|
||||
`75fd6d4053b0ffe636b298f3c514222a9a5adf9a316d211ebabb8ccb58c2a89a`;
|
||||
diagnostic lock SHA-256
|
||||
`4b426c7b38b765f1ae7e6947dcb52e21dc26a02ed4d50ba51354819a918a83c8`.
|
||||
|
||||
The initial diagnostic failures exposed an invalid external-content check for
|
||||
the sparse index and milliseconds supplied to nanosecond storage. Both were
|
||||
corrected in the harness; production engine behavior was unchanged. Statistics
|
||||
tests passed in normal and optimized Python modes; formatting and strict
|
||||
release all-target Clippy passed. A subsequent Clippy-only parity-expression
|
||||
cleanup did not change the recorded smoke executable. The million-record run,
|
||||
representative libraries and UI/semantic timings remain open.
|
||||
Reference in new issue
Block a user