0d0fbf36c9
Verifies the FilterIndex path in LiveEventStore: each event matches exactly ONE of N subscribers, so without an index the relay walks all N subs per event (O(N)); with the author-keyed index the lookup is O(1) and per-event latency stays flat as N grows. Different from fanoutLatency (broadcast: 1 event reaches every sub). Here per-event work is lookup-bound rather than delivery-bound. Configurable via -DfanoutScalingSubs (comma list) and -DfanoutScalingEvents. Measured (laptop, JDK 21, full sweep): 100 subs, 2k events: p50=1.35ms p99=5.71ms 1000 subs, 2k events: p50=1.05ms p99=3.05ms 5000 subs, 1k events: p50=1.01ms p99=2.96ms p50 ~1ms across N — the predicted O(1) scaling. Default events count adapts downward at high N to stay below WebSocketSessionPump's 8192-frame outbound cap (test-client read side is the bottleneck above ~5k subs, not the relay). Plan doc updated with the measured numbers in the "How to verify" section.
geode plans
Performance-focused design docs for future work. Each file is a self-contained sketch — problem statement, observed numbers, proposed fix, how to verify, risks. None of these are committed work; they're the queue.
Ordered roughly by expected impact:
| Plan | Headline gain |
|---|---|
| 2026-05-07-event-ingestion-batching.md | 5–10× write EPS via SQLite group commit + ingest pipelining |
| 2026-05-07-live-broadcast-fanout-index.md | >10× fanout speedup at >2 000 subscribers |
| 2026-05-07-connection-scaling.md | 2 000 → 10 000+ concurrent connections |
| 2026-05-07-negentropy-large-corpus.md | 25× lower memory + faster NEG-OPEN on M-event corpora |
Verification target for each plan is a new method on
geode.perf.LoadBenchmark (gated by -DrunLoadBenchmark=true) so
regressions show up in the regular CI matrix once they're enabled.