Skip to content

P2: Fix performance bottlenecks in scan/review pipeline #335

Description

@ajianaz

Summary

Cora scan found 10 performance issues, all sharing the same pattern: repeated expensive operations inside loops that should be done once.

Issues

Regex recompiled per line (#41src/engine/rules/matching.rs:36)

Regex::new(&rule.pattern) called for every line of every rule. Should precompile once when loading rules.

Fix: Store compiled regex alongside each rule, compile once at load time.

Per-file DB queries in nested loops (#5src/mcp/tools.rs:528)

handle_find_affected_tests runs SQL per file → per symbol → per test pattern. Classic N+1 query pattern.

Fix: Batch lookups, prepare statements once, deduplicate before traversal.

Affected test analysis repeated graph lookups (#13src/main.rs:844)

Same N+1 pattern in the Affected command — queries symbols per file, callers per symbol.

Fix: Fetch all symbols for all files in one query, resolve callers in fewer set-based queries.

Prepared statement recreated in inner loop (#14src/main.rs:888)

conn.prepare(...) called inside test-pattern loop for every changed file.

Fix: Prepare once before loop, reuse statement.

Secrets scanner no early cutoff (#59src/engine/secrets_scanner.rs:137)

Scans all files/hunks/lines even after max_findings reached. Capped only after full scan.

Fix: Check findings.len() >= max_findings during scan and break early.

Symbol cap does not stop file scanning (#70src/engine/context/extraction.rs:281)

break exits only inner symbol loop, not the line iteration loop.

Fix: Add labeled break or guard before line extraction.

Repeated file reads during sibling search (#67 — `src/engine/context/resolver.rs:447)

resolve_function and resolve_type read same files from disk repeatedly.

Fix: Introduce file-content cache keyed by path for duration of context build.

New Tokio runtime per MCP tool call (#3src/mcp/tools.rs:643)

handle_review_diff creates fresh tokio::runtime::Runtime for every request.

Fix: Create and reuse single runtime for server lifetime.

Regex recompiled per line in detect_function_entry (#22src/index/extract.rs:423)

Creates new Regex instances per call. Module already uses LazyLock statics.

Fix: Move to static LazyLock<Regex> values.

Per-file transaction for prune_deleted (#24src/index/mod.rs:249)

Starts/commits separate transaction per deleted file.

Fix: Open one transaction before loop, commit once at end.

Effort estimate: 1-2 days

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions