tidaldb/docs/profiling/scale-baselines.md
jx12n 6651c14adc feat(m11): cluster security (m11p7) + perf instrumentation floor
m11p7 — secure the cluster, all opt-in (pre-m11p7 byte-for-byte):
- gRPC replication mTLS by default via a custom tokio-rustls acceptor +
  DynamicCertResolver; zero-drop content-hash cert rotation (k8s ..data swap,
  no pod restart, no inotify)
- inter-node HTTP TLS sharing the same resolver (one rotation, both planes) +
  per-node keyed-BLAKE3 signed x-tidal-node-token; marker-without-token -> 403
- admin audit log (operator-leg only) + per-principal rate limit (engine
  RateLimiter; sibling nodes exempt)
- k8s cert-manager manifest (certs.yaml) + scripts/gen-cluster-certs.sh fallback;
  secret.example.yaml gains TIDAL_CLUSTER_KEY (file-mounted, hot-rotatable)
- exit gate verified real: mtls.rs (gRPC foreign-pod), cluster_security.rs
  (HTTP foreign + zero-drop rotation under load), 7 security unit tests

perf — instrument floor (sweep Wave 1):
- new tidal/benches/wal.rs + tidal-server/benches/scatter.rs
- p99->mean honesty relabel; sweep manifest at docs/reviews/perf-sweep-2026-06-13.md
- add @tidal-performance agent (Martin Thompson)

new: cluster/{audit,http_tls,security}.rs, tests/cluster_security.rs,
docs/planning/milestone-11/phase-7.md
2026-06-13 01:25:35 -06:00

4.7 KiB
Raw Blame History

Scale Benchmarks: 1M-Item Baselines

Hardware

macOS Darwin 23.6.0 (Apple Silicon / x86-64 — see run date below).

Run command:

cargo bench --manifest-path tidal/Cargo.toml --bench scale

Date: 2026-02-23

Dataset

Parameter Value
Items 1,000,000
Creators 10,000 (100 items/creator)
Categories 20
Embedding dim 128 (not 1536 — reduced for bench RAM)
Signal coverage 10% view, 5% like
Bench tool Criterion (sample_size=10, 30s measurement, Flat mode) — closed-loop, single-threaded; reports the mean, not the tail

Measurement contract (read before trusting any number below)

The time: figures Criterion reports are single-threaded mean per-op cost under a closed loop — the [lower mean upper] triple is a confidence interval on the mean, not a latency distribution. They are regression tripwires, not tail-SLO evidence.

A p99/p999/tail SLO can only be honored by an open-loop, coordinated-omission-corrected measurement under real concurrency (the tidal-stress ramp). A closed-loop mean cannot observe the tail it hides: when the system stalls, a closed-loop harness simply stops sending, so the queue that would inflate p99 never forms. Reporting a mean under a p99 label understates the tail by 10100× under load.

Therefore every row below is labelled isolated per-op cost (mean). Tail SLOs are validated separately — see tidal-stress (open-loop) for the authoritative p99/p999 under the production workload.

Acceptance Criteria (isolated per-op cost — regression tripwires, NOT tail SLOs)

Benchmark Tail SLO (validated open-loop) Isolated per-op cost (mean, closed-loop) Tripwire
RETRIEVE < 50ms p99 152 µs (for_you) well under
SEARCH < 100ms p99 28.9 ms (text_only) well under
Signal write < 100µs p99 82 ns (rotating 1K) well under

The mean per-op costs sit far under the tail targets — a necessary but not sufficient condition for the p99 SLO. "Well under" means the mean clears the target with headroom; the p99 itself is signed off only by the open-loop tidal-stress run, never by this table.

Benchmark Results

RETRIEVE (1M items)

retrieve_1m/for_you          time:   [151.88 µs 152.13 µs 152.40 µs]
retrieve_1m/trending         time:   [127.96 µs 128.25 µs 128.52 µs]
retrieve_1m/new_filtered     time:   [  7.5636 µs   7.5855 µs   7.6058 µs]

All RETRIEVE queries < 200µs. The 50ms target is beaten by 3 orders of magnitude.

  • for_you: signal-scored ranking over full 1M-item universe — 152µs
  • trending: windowed view count ranking — 128µs
  • new_filtered: category filter at ~5% selectivity — 7.6µs (bitmap pre-filter eliminates 95% of candidates)

SEARCH (1M items)

search_1m/text_only          time:   [28.844 ms 28.934 ms 29.021 ms]
search_1m/text_filtered      time:   [ 1.8972 ms  1.9104 ms  1.9220 ms]

Both SEARCH queries < 30ms. The 100ms target is beaten by 3-50×.

  • text_only: BM25 over 1M documents — 28.9ms (most expensive path; dominated by Tantivy posting list traversal)
  • text_filtered: BM25 with category filter reduces candidate set — 1.9ms

Signal Write (1M-item DB, rotating 1K entities)

signal_write_1m/write_rotating_1k_entities    time:   [82.033 ns 82.286 ns 82.535 ns]

82 ns per write. The 100µs target is beaten by 1,200×. DashMap hot-path write amortises to sub-100ns across 1K rotating entity IDs.

Setup Notes

The LazyLock<TidalDb> pattern ensures the 1M-item database is built exactly once per bench run. Build time ~30s on the reference hardware above. The text syncer waits 3s after ingestion.

Database Build Time

Approximately 30 seconds on reference hardware (observed from [scale bench] Database ready log line).

Analysis

tidalDB's isolated per-op mean cost sits well within all three acceptance-criteria targets at 1M items. The dominant cost is SEARCH text_only at ~29ms — driven by Tantivy posting list traversal across 1M documents. The LogMergePolicy tuning (< 20 segments at steady state) keeps this below the 100ms target with headroom. The p99 tail SLOs themselves are signed off by the open-loop tidal-stress ramp, not by these closed-loop means (see the measurement contract above).

Signal writes at 82ns confirm the DashMap hot-path is not a bottleneck at this scale. The 5M-entry LRU trimming threshold (DEFAULT_MAX_SIGNAL_ENTRIES) provides ample headroom for the 100K-item signal coverage in this benchmark (~200K entries = ~218MB).