Skip to content

rust-analyzer hangs at 100% CPU in PrimeCaches after 1.93.1 #23346

Description

@chenyh1990

rust-analyzer version:

Working version: 1.93.1

First known affected version: 1.94.1

Also reproduced with: 1.97.1, 1.98.0

rustc version:

rustc 1.97.1

editor or extension:

VSCode

relevant settings:

Large Rust monorepo with approximately 736 crates.

The issue occurs during cache priming.

I also tested with:

"rust-analyzer.cachePriming.numThreads": 1

and the issue still reproduces.

repository link (if public, optional):

Private repository.

code snippet to reproduce:

The issue only reproduces in our large private monorepo, so I currently do not have a minimal reproduction.

Description

There appears to be a severe performance regression between rust-analyzer 1.93.1 and 1.94.1.

With 1.93.1, the workspace loads normally and cache priming eventually completes.

Starting from 1.94.1, rust-analyzer can get stuck indefinitely during cache priming with approximately 100% CPU usage.

I also reproduced the issue with 1.97.1 and 1.98.0.

The crate shown as the last crate in the progress indicator is not deterministic. For example, one run stopped around:

734/736 (validate_proto)

but other runs stopped at different crates near the end of the workspace.

The rust-analyzer process then remains at approximately 100% CPU without making further progress.

Profiling

I profiled the affected process with perf.

The profile shows that the CPU time is overwhelmingly spent in the PrimeCaches#3 worker.

With symbols resolved, the profile is:

99.55%    99.55%  PrimeCaches#3  rust-analyzer
             [.] syntax_bridge::to_parser_input::to_parser_input

 0.36%     0.00%  PrimeCaches#3  [kernel.kallsyms]
             [.] asm_sysvec_apic_timer_interrupt
 0.35%     0.00%  PrimeCaches#3  [kernel.kallsyms]
             [.] sysvec_apic_timer_interrupt
 ...

In particular, approximately 99.55% of sampled CPU cycles are spent in:

syntax_bridge::to_parser_input::to_parser_input

inside:

PrimeCaches#3

This appears to be CPU-bound rather than rust-analyzer simply waiting for I/O.

Comparison with 1.93.1

With 1.93.1, cache priming eventually completes. For example, the log contains:

2026-09-12T07:33:59.962612001Z WARN overly long loop turn took 714.964958ms: (event handling took 683.121163ms): PrimeCaches(End { cancelled: false }) (cancellation took None) (garbage collection took Some(31.784941ms))

The important part is:

PrimeCaches(End { cancelled: false })

which indicates that cache priming eventually reaches the end.

With the affected versions, cache priming does not reach the corresponding completion state and the process remains CPU-bound.

numThreads = 1

I also tested:

"rust-analyzer.cachePriming.numThreads": 1

The issue still reproduces.

Therefore, the problem does not appear to require multiple cache-priming worker threads.

Version boundary

The behavior can be summarized as:

1.93.1  -> works
1.94.1  -> hangs
1.97.1  -> hangs
1.98.0  -> hangs

Given the clear version boundary and the perf profile, I suspect a regression in the syntax/query/cache-priming path introduced between 1.93.1 and 1.94.1.

In particular, syntax_bridge::to_parser_input::to_parser_input seems worth investigating.

A full perf call graph can be provided if useful.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Broken WindowBugs / technical debt to be addressed immediatelyC-bugCategory: bugI-hangIssue: The analysis never terminates, due to infinite loops, deadlock, livelock, etc.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions