Skip to content

perf: reuse singleton analyzer instances in C#/Go/Java/Python/Rust analyzeFile() - #580

Merged
askpt merged 2 commits into
mainfrom
repo-assist/improve-analyzer-singletons-20260828-500dce4b4b8f24b3
Aug 29, 2026
Merged

perf: reuse singleton analyzer instances in C#/Go/Java/Python/Rust analyzeFile()#580
askpt merged 2 commits into
mainfrom
repo-assist/improve-analyzer-singletons-20260828-500dce4b4b8f24b3

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

🤖 This PR was created by Repo Assist, an automated AI assistant.

What

Extends the module-level singleton pattern (already applied to the JS/TS/TSX analyzers in #578) to the five remaining language analyzers: C#, Go, Java, Python, and Rust.

Why

Each of these analyzeFile() static methods allocated a brand-new analyzer instance on every call, even though analyzeFunctions() already resets all mutable per-analysis state (nesting, complexity, details, etc.) at the start of each top-level function analysis. Reusing a single module-level instance avoids an unnecessary object allocation on every file the CodeLens provider analyzes, which happens frequently during editing.

Trade-offs

  • None functionally: the reset-on-entry pattern already made the underlying analyzer classes safe to reuse across calls (this was previously verified when the same pattern was applied to JS/TS/TSX).
  • The Parser instance was already a module-level singleton in every language analyzer; only the outer *MetricsAnalyzer wrapper object is now also reused.

Test Status

  • npm run compile: clean
  • npm run lint: clean
  • npm run test:unit: 236 passing (unchanged)
  • Coverage: 98.72% stmts / 94.99% branch / 99.1% funcs / 98.72% lines (thresholds 95/88/97/95 — met)

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • releaseassets.githubusercontent.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "releaseassets.githubusercontent.com"

See Network Configuration for more information.

Generated by 🌈 Repo Assist, see workflow run. Learn more.
Comment /repo-assist to run again

Add this agentic workflow to your repo

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md@42c2ab5b4e4c9273534c39259b2e0df7f20f07e9

…alyzeFile()

Applies the same module-level singleton pattern already used by the
JS/TS/TSX analyzers (see #578) to the remaining five language analyzers.
Each previously allocated a new analyzer instance on every analyzeFile()
call; since analyzeFunctions() resets all mutable state (nesting,
complexity, details) at the start of each top-level function analysis,
reusing one instance per language is safe and avoids unnecessary
allocations on every file analyzed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@askpt askpt changed the title [repo-assist] perf: reuse singleton analyzer instances in C#/Go/Java/Python/Rust analyzeFile() perf: reuse singleton analyzer instances in C#/Go/Java/Python/Rust analyzeFile() Aug 29, 2026
@codecov

codecov Bot commented Aug 29, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.03%. Comparing base (b24f965) to head (77aecd9).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #580      +/-   ##
==========================================
+ Coverage   98.02%   98.03%   +0.01%     
==========================================
  Files          12       12              
  Lines        3901     3926      +25     
  Branches      450      450              
==========================================
+ Hits         3824     3849      +25     
  Misses         77       77              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@askpt
askpt marked this pull request as ready for review August 29, 2026 09:23
@askpt
askpt self-requested a review as a code owner August 29, 2026 09:23
Copilot AI balanced review requested due to automatic review settings August 29, 2026 09:23

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The C# singleton can retain a cached syntax node and its parse tree indefinitely.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Reuses module-level analyzer instances to reduce allocations during repeated file analysis.

Changes:

  • Adds singleton reuse for C#, Go, Java, Python, and Rust analyzers.
  • Documents the singleton rationale.
File summaries
File Description
csharpAnalyzer.ts Reuses a C# analyzer singleton.
goAnalyzer.ts Reuses a Go analyzer singleton.
javaAnalyzer.ts Reuses a Java analyzer singleton.
pythonAnalyzer.ts Reuses a Python analyzer singleton.
rustAnalyzer.ts Reuses a Rust analyzer singleton.
Review details
  • Files reviewed: 5/5 changed files
  • Comments generated: 1
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/metricsAnalyzer/languages/csharpAnalyzer.ts
Co-authored-by: askpt <2493377+askpt@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The singletons retain the last source text and detail array indefinitely, introducing avoidable memory retention.

Review details

Suppressed comments (5)

Previously missed (4) — in code that hasn't changed since the last review.

src/metricsAnalyzer/languages/goAnalyzer.ts:611

  • Reusing this analyzer now keeps the entire last Go source string and the final function's detail array reachable for the lifetime of the loaded module (and an empty subsequent file does not reset details). Previously the per-call analyzer released this state once its result was no longer referenced. Clear both reference fields in a finally block after the synchronous analysis.
    return _analyzerInstance.analyzeFunctions(sourceText);

src/metricsAnalyzer/languages/javaAnalyzer.ts:423

  • Reusing this analyzer now keeps the entire last Java source string and the final method's detail array reachable for the lifetime of the loaded module (and an empty subsequent file does not reset details). Previously the per-call analyzer released this state once its result was no longer referenced. Clear both reference fields in a finally block after the synchronous analysis.
    return _analyzerInstance.analyzeFunctions(sourceText);

src/metricsAnalyzer/languages/pythonAnalyzer.ts:392

  • Reusing this analyzer now keeps the entire last Python source string and the final function's detail array reachable for the lifetime of the loaded module (and an empty subsequent file does not reset details). Previously the per-call analyzer released this state once its result was no longer referenced. Clear both reference fields in a finally block after the synchronous analysis.
    return _analyzerInstance.analyzeFunctions(sourceText);

src/metricsAnalyzer/languages/rustAnalyzer.ts:450

  • Reusing this analyzer now keeps the entire last Rust source string and the final function's detail array reachable for the lifetime of the loaded module (and an empty subsequent file does not reset details). Previously the per-call analyzer released this state once its result was no longer referenced. Clear both reference fields in a finally block after the synchronous analysis.
    return _analyzerInstance.analyzeFunctions(sourceText);

src/metricsAnalyzer/languages/csharpAnalyzer.ts:942

  • Reusing this analyzer now keeps the entire last C# source string and the final function's detail array reachable for the lifetime of the loaded module (and an empty subsequent file does not reset details). Previously the per-call analyzer released this state once its result was no longer referenced. Clear both reference fields in a finally block after the synchronous analysis.
    return _analyzerInstance.analyzeFunctions(sourceText);
  • Files reviewed: 5/5 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

@askpt
askpt merged commit c8d989e into main Aug 29, 2026
11 checks passed
@askpt
askpt deleted the repo-assist/improve-analyzer-singletons-20260828-500dce4b4b8f24b3 branch August 29, 2026 10:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants