Skip to content

Rust perf: push ledger Query filters into SQL + adopt prepare_cached #324

@willwashburn

Description

@willwashburn

Context

crates/relayburn-sdk/src/ledger/reader.rs:32-53 (query_turns) and :121-142 (select_records) load every row of a table into Vec<String> and then filter in Rust. The Query filters are pure SQL predicates with existing indexes (idx_turns_ts, idx_turns_session):

  • since / untilWHERE rowid >= ? AND rowid <= ? (or whatever timestamp column maps to idx_turns_ts).
  • session_idWHERE session_id = ?.
  • sourceWHERE source = ?.

Every call we re-parse JSON for thousands of turns we then throw away. This is the biggest ledger perf win available.

Adjacent: no prepare_cached anywhere in the ledger. The TS sibling got prepared-statement caching free from better-sqlite3; the rusqlite port lost it. With burn ingest --watch firing ingest_all every second, every read goes through full prepare/teardown.

Proposed fix

  1. Build WHERE/parameter pairs from Query and bind them via params!. Keep relationship_passes (currently does serde_json::to_value enum→string round-trips per row) but make the source comparison a single &'static str from a wire_str() method rather than per-row Value alloc — see #(forthcoming enum-string-conversion issue).
  2. Switch every hot SELECT in ledger/reader.rs to Connection::prepare_cached. Writers can stay one-shot inside their own transaction since they're already amortized.
  3. Consider gating collect_stamps (ledger/reader.rs:144-176) on a Query flag — today it folds every stamp into every turn, even when the caller never reads enrichment.

Verification

  • Conformance gate (deep-equal vs TS @relayburn/sdk) must keep passing.
  • Add a benchmark over a large fixture — expected speedup is order-of-magnitude on --since queries against a many-month ledger.

References

  • crates/relayburn-sdk/src/ledger/reader.rs:32-53, 121-142, 144-176, 269-277, 365
  • Companion fingerprint hot-path: crates/relayburn-sdk/src/ledger/fingerprint.rs:118 allocates a Value per record just to read out the source string.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions