Files
Huang Xin 2d819b476c fix(db): forward DatabaseOpts to tauri-plugin-turso (#4292)
* fix(db): forward DatabaseOpts to tauri-plugin-turso

NativeDatabaseService.open ignored its opts parameter, dropping any
experimental feature flags (e.g. 'index_method' needed for FTS / vector
indexes) and any encryption config before they could reach the Tauri
plugin. Translate DatabaseOpts to the plugin's LoadOptions shape and
forward as the single argument Database.load accepts. Skip translation
when no relevant opts are set so the existing path-string call shape is
preserved for callers without experimental/encryption needs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test(db): cover Turso vector primitives + add benchmark harness

Verifies the Turso functions Reedy retrieval depends on, with a
brute-force per-book kNN test that runs against every DatabaseService
backend (node, native, WASM):

  SELECT vector_distance_cos(embedding, vector32(?)) AS d
    FROM book_chunks
   WHERE book_hash = ?
   ORDER BY d ASC LIMIT k

This is the path Turso's own founder recommended in
tursodatabase/turso#3778 ("First, focus on efficient SIMD-accelerated
brute-force search") and what shipped at commit 1aba105df4f. Native
vector index modules don't exist in this engine: `libsql_vector_idx`,
`vector_top_k`, and `USING vector/hnsw/diskann/ivfflat` all parse-error
against @tursodatabase/database@0.6.0-pre.28 (libsql_vector_idx is a
libSQL/sqld fork feature; DiskANN was closed not-planned upstream in
#832). The test asserts cross-book isolation and nearest-first ordering
using only `WHERE book_hash = ?` and `ORDER BY` — no DDL, no identifier
interpolation, no index plumbing.

Also adds bench/ harness for manual perf checks:

  pnpm bench [name]            run benchmarks (refuses in CI)
  pnpm bench --list            list available benchmarks
  pnpm bench --no-record       skip results.jsonl append
  pnpm bench --force           override the CI guard

Uses Node 24's --experimental-strip-types so no tsx devDep is needed.
Appends one JSON line per run to bench/results.jsonl (gitignored, local
history; share by pasting tabular stdout into PRs/issues). Explicitly
NOT in CI — shared-tenant variance makes synthetic-benchmark regression
detection unreliable; production telemetry (reedy_metrics, plan §M1.9)
is the right tool for that.

First benchmark: vector-retrieval. Measured on M1 Pro:
  400 chunks ×  384 dim  →  0.35 ms / query
  400 chunks ×  768 dim  →  0.45 ms / query
  2000 chunks × 768 dim  →  2.23 ms / query
  10000 chunks × 768 dim → 14.00 ms / query
  400 chunks × 1536 dim  →  0.70 ms / query

Per-chunk cost ~1.1 µs at 768 dim = ~1.4 ns/dim. NEON-class on
Apple Silicon, ~50× faster than scalar — confirms SIMD acceleration is
active in 0.6.0-pre.28. Per-query latency stays sub-ms at Reedy MVP
corpus sizes; the ceiling is ~10K chunks per book before phone-class
hardware notices.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 18:51:49 +02:00
..

Benchmarks

Manual performance benchmarks for the readest-app. Not run in CI — CI runners have shared-tenant variance that makes performance regression detection unreliable (numbers swing 2-10× between runs). These exist so anyone considering an architecture change can produce reproducible before/after numbers on their own hardware.

Run

pnpm bench                       # run every bench/*.bench.ts
pnpm bench vector-retrieval      # run a single benchmark by name
pnpm bench --no-record           # run but don't append to bench/results.jsonl
pnpm bench --list                # list available benchmarks

Refuses to run when $CI is set. Append --force to override (don't unless you've explicitly opted into running benches in CI for a one-off investigation).

Output

Each run prints a header with machine info (platform, CPU, Node version, key package versions) followed by per-benchmark results. By default, results are also appended to bench/results.jsonl (gitignored) — your personal local history. To share numbers, paste the table from the terminal into a PR or issue.

When to add a new benchmark

When you're proposing an architecture change and need numbers to defend it. The benchmark should:

  1. Live at bench/<name>.bench.ts.
  2. Export default { name, description, run(ctx) } matching the type in lib.ts.
  3. Print human-readable results to stdout and return structured results to the harness so they get logged to results.jsonl.
  4. Be self-contained — no fixtures outside bench/, no I/O outside the bench directory and an in-memory database.
  5. Run in under ~30 seconds at default sample sizes. If you need long-running scenarios, gate them behind a CLI flag.

When not to add a benchmark

  • "Just in case" — performance infrastructure has carrying cost. Wait until you have a real architecture question that numbers will answer.
  • To benchmark upstream libraries' performance (e.g., raw Turso function throughput). That belongs in the upstream project's bench suite.
  • To gate CI on performance thresholds. CI variance makes that flaky; use production telemetry (reedy_metrics table) for regression detection against real workloads.

Existing benchmarks

  • vector-retrieval — proves Turso's brute-force vector search is SIMD-accelerated and fast enough for Reedy MVP corpus sizes (sub-millisecond at 400 chunks × 768 dim, ~14 ms at 10K chunks × 768 dim). Established the decision in plan §M1.5 to skip ANN indexes (which Turso doesn't ship anyway).