Skip to content

Rust perf: stop cloning whole turn streams in analyze hot paths #325

@willwashburn

Description

@willwashburn

Context

Multiple analyze-module hot paths clone the full input Vec<TurnRecord> before they aggregate, doubling the working-set memory of the most expensive verbs. Every TurnRecord carries a Vec<ToolCall> plus optional file lists — these are not cheap clones.

Concrete sites:

  • crates/relayburn-sdk/src/analyze/overhead.rs:131-136 — clones every applicable TurnRecord per overhead file, . With three default candidates and overlapping applies_to, every Claude turn ends up cloned ~2× and every Codex/OpenCode turn ~1×. Biggest unforced alloc in the analyzer.
  • crates/relayburn-sdk/src/analyze/hotspots.rs:208-216 — the entire turn stream cloned into IndexMap<String, Vec<TurnRecord>> via entry(t.session_id.clone()).or_default().push(t.clone()).
  • crates/relayburn-sdk/src/analyze/quality.rs:113-124 — parallel Vec<(String, Vec<TurnRecord>)> + HashMap<String, usize> index, cloning every turn.
  • crates/relayburn-sdk/src/analyze/compare.rs:127-152 — model id cloned 4× per turn inside the hot accumulation loop (lines 132, 140, 143, 147).

Proposed fix

Switch the per-session/per-file aggregations to Vec<&TurnRecord> (or IndexMap<String, Vec<&TurnRecord>>). Nothing downstream of these sites mutates the turns; they only read them. The lifetime should already trivially be the input slice.

For compare.rs:127-152 specifically: hoist the model-name clone above the entry/or_insert_with calls (one clone per new model, not per turn).

Also fold in:

  • crates/relayburn-sdk/src/analyze/overhead.rs:170-177 describe_applies_to — three serde_json::to_value round-trips on every call to discover that SourceKind::ClaudeCode serializes to \"claude-code\". A 4-arm match returning &'static str removes 3 allocs per file render. (Belongs with the enum-string-conversion follow-up too.)

Verification

The conformance gate (deep-equal results vs TS @relayburn/sdk) is the existing safety net; behavior must not change.

References

  • Analyze review notes from the May 2026 Rust review.

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