Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rust-analyzer consumes huge amounts of RAM and gets stuck #16050

Closed
NickAcPT opened this issue Dec 8, 2023 · 10 comments · Fixed by #16054
Closed

rust-analyzer consumes huge amounts of RAM and gets stuck #16050

NickAcPT opened this issue Dec 8, 2023 · 10 comments · Fixed by #16054
Assignees
Labels
A-macro macro expansion Broken Window Bugs / technical debt to be addressed immediately C-bug Category: bug

Comments

@NickAcPT
Copy link

NickAcPT commented Dec 8, 2023

While trying to work on a specific file on my project, r-a starts using all memory available.
image

I attempted to get a Memory Usage from r-a while it was consuming memory, but I don't know how accurate it is:

Memory Usage

Per-query memory usage:
117mb 10108 FileTextQuery
11mb 320 CrateDefMapQueryQuery
10mb 223921 LangAttrQuery
10mb 131525 InternFunctionQuery
10mb 131620 InternConstQuery
10mb 75623 InternMacroCallQuery
8mb 147795 InternSyntaxContextQuery
4mb 109534 InternImplQuery
3856kb 78483 ImplSelfTyQuery
3812kb 69351 AstIdMapQuery
3752kb 78483 ImplTraitQuery
3480kb 64745 ParseMacroExpansionQuery
1288kb 77 ImportMapQuery
1232kb 39884 MacroArgQuery
1116kb 947 DeclMacroExpanderQuery
1060kb 26941 InternTypeAliasQuery
0b 1 ProcMacrosQuery
0b 10108 FileSourceRootQuery
0b 366 SourceRootQuery
0b 1 SourceRootCratesQuery
0b 35 StructDataQuery
0b 35 StructDataWithDiagnosticsQuery
0b 0 UnionDataQuery
0b 0 UnionDataWithDiagnosticsQuery
0b 1023 TraitDataQuery
0b 0 TraitAliasDataQuery
0b 338 TypeAliasDataQuery
0b 32 ConstDataQuery
0b 0 StaticDataQuery
0b 0 Macro2DataQuery
0b 0 MacroRulesDataQuery
0b 0 ProcMacroDataQuery
0b 41 ExprScopesQuery
0b 2 FieldsAttrsQuery
0b 0 VariantsAttrsSourceMapQuery
0b 2 FieldsAttrsSourceMapQuery
0b 187 LangItemQuery
0b 40 FieldVisibilitiesQuery
0b 44 FunctionVisibilityQuery
0b 3 ConstVisibilityQuery
0b 0 CrateSupportsNoStdQuery
0b 0 ExternCrateDeclDataQuery
0b 0 InternAnonymousConstQuery
0b 208 InternExternCrateQuery
0b 21881 InternUseQuery
0b 44 MirBodyQuery
0b 13127 TyQuery
0b 80 ValueTyQuery
0b 700 ConstParamTyQuery
0b 8 ConstEvalQuery
0b 9 ConstEvalDiscriminantQuery
0b 45 FieldTypesQuery
0b 5 LayoutOfAdtQuery
0b 16 TargetDataLayoutQuery
0b 85 CallableItemSignatureQuery
0b 29 ReturnTypeImplTraitsQuery
0b 219 GenericPredicatesForParamQuery
0b 50 TraitEnvironmentQuery
0b 11 InherentImplsInBlockQuery
0b 70 InternCallableDefQuery
0b 0 InternLifetimeParamIdQuery
0b 0 InternImplTraitIdQuery
0b 15 InternTypeOrConstParamIdQuery
0b 0 InternClosureQuery
0b 0 InternGeneratorQuery
0b 38 AssociatedTyDataQuery
0b 43 StructDatumQuery
0b 0 FnDefDatumQuery
0b 0 FnDefVarianceQuery
0b 42 AdtVarianceQuery
0b 190 AssociatedTyValueQuery
0b 0 ModuleSymbolsQuery
0b 0 LibrarySymbolsQuery
0b 1 LocalRootsQuery
0b 1 LibraryRootsQuery
0b 1 LineIndexQuery
0b 18367 InternStructQuery
0b 512 InternUnionQuery
0b 2061 InternEnumQuery
0b 309 InternStaticQuery
0b 1739 InternTraitQuery
0b 1 InternTraitAliasQuery
0b 8420 InternExternBlockQuery
0b 419 InternBlockQuery
0b 42 InternMacro2Query
0b 102 InternProcMacroQuery
0b 1665 InternMacroRulesQuery
-4096b 4849 RealSpanMapQuery
-4096b 1032 EnumDataQuery
-4096b 419 BlockItemTreeQueryQuery
-4096b 18 TraitImplsInBlockQuery
-8kb 419 BlockDefMapQuery
-8kb 103 InternInTypeConstQuery
-8kb 6 IncoherentInherentImplCratesQuery
-8kb 33 ProgramClausesForChalkEnvQuery
-12kb 1032 EnumDataWithDiagnosticsQuery
-12kb 44 InferQueryQuery
-12kb 61 TraitDatumQuery
-16kb 7779 ImplDatumQuery
-56kb 28 BorrowckQuery
-60kb 158 InherentImplsInCrateQuery
-72kb 78484 ImplDataQuery
-132kb 1099 TraitSolveQueryQuery
-140kb 1 CrateGraphQuery
-144kb 487 BodyQuery
-144kb 933 VariantsAttrsQuery
-144kb 160 TraitImplsInCrateQuery
-152kb 108 CrateLangItemsQuery
-256kb 7935 GenericPredicatesQuery
-272kb 459 ExpandProcMacroQuery
-276kb 4 TraitImplsInDepsQuery
-280kb 868 FunctionDataQuery
-364kb 13925 GenericDefaultsQuery
-560kb 1023 TraitDataWithDiagnosticsQuery
-976kb 78484 ImplDataWithDiagnosticsQuery
-992kb 487 BodyWithSourceMapQuery
-1840kb 92752 GenericParamsQuery
-4mb 4849 ParseQuery
-44mb 68955 FileItemTreeQuery
-52mb 234390 AttrsQuery
6063mb Remaining

(note: database has been cleared)

I haven't figured out what exactly is causing it to start consuming all the RAM, but I can reproduce it consistently on my project. (apologies for not having a minimal reproduction example).

The issue perhaps seems to be perhaps caused by the json! macro, since attempting to hover any variables inside it causes r-a to get stuck.
image 2

Steps:

  1. Clone repository
$ git clone https://github.com/NickAcPT/nmsr-rs.git && cd nmsr-rs && git switch --detach e6210000304798ea7483e11ca0da9bc84f8f2a34
  1. Open file utils\nmsr-rendering-blockbench-model-generator-experiment\src\blockbench\model.rs
  2. Scroll to around line 125.
  3. Attempt to hover some variables inside the json! macro
  4. Watch the world burn RAM being consumed

rust-analyzer version: (eg. output of "rust-analyzer: Show RA Version" command, accessible in VSCode via Ctrl/⌘+Shift+P)
rust-analyzer version: 0.4.1761-standalone (bc9c952 2023-12-07)

rustc version: (eg. output of rustc -V)
rustc 1.74.0 (79e9716c9 2023-11-13)

relevant settings: (eg. client settings, or environment variables like CARGO, RUSTC, RUSTUP_HOME or CARGO_HOME)

{
    "rust-analyzer.cargo.features": [
        "ears",
        "part_tracker"
    ],
    "rust-analyzer.assist.emitMustUse": true,
    "rust-analyzer.procMacro.ignored": {
        "tokio-macros": [
            "main"
        ],
        "axum": [
            "debug_handler"
        ]
    },
    "rust-analyzer.inlayHints.lifetimeElisionHints.enable": "skip_trivial",
    "rust-analyzer.inlayHints.lifetimeElisionHints.useParameterNames": true,
    "rust-analyzer.inlayHints.closingBraceHints.enable": false,
    "rust-analyzer.inlayHints.expressionAdjustmentHints.enable": "reborrow",
    "rust-analyzer.inlayHints.expressionAdjustmentHints.hideOutsideUnsafe": true,
    "rust-analyzer.inlayHints.reborrowHints.enable": "mutable",
    "rust-analyzer.imports.prefix": "crate",
    "rust-analyzer.imports.granularity.enforce": true,
    "rust-analyzer.check.allTargets": false,
    "rust-analyzer.inlayHints.implicitDrops.enable": true,
    "rust-analyzer.diagnostics.experimental.enable": false,
}
@NickAcPT NickAcPT added the C-bug Category: bug label Dec 8, 2023
@wyatt-herkamp
Copy link
Contributor

wyatt-herkamp commented Dec 8, 2023

So @NickAcPT was telling about this issue and I did not believe him at first. So I tested it on my PC.

PC Specs

OS: Windows 11  
Rust-Version: rustc 1.74.0 (79e9716c9 2023-11-13)  
Ram: 64GB  
CPU Ryzen 9 7950X  
rust-analyzer version: 0.4.1761-standalone (bc9c952b6 2023-12-07)

I watched the memory usage climb to 36000mb before I killed Rust Analyzer.

@lnicola
Copy link
Member

lnicola commented Dec 8, 2023

What happens if you run rust-analyzer analysis-stats .? You can download it from GitHub or find it under the locations listed in https://rust-analyzer.github.io/manual.html#vs-code.

@NickAcPT
Copy link
Author

NickAcPT commented Dec 8, 2023

I attempted to get some log information by setting RA_LOG=info, and this is what I got. I had to kill r-a before my PC ran out of memory.
For some reason VSC didn't keep the whole info text in the output panel, but I believe it should still help.

@lnicola
Copy link
Member

lnicola commented Dec 8, 2023

I can reproduce even without build scripts and proc macros. CC @Veykril this is on nightly.

@NickAcPT
Copy link
Author

NickAcPT commented Dec 8, 2023

What happens if you run rust-analyzer analysis-stats .? You can download it from GitHub or find it under the locations listed in rust-analyzer.github.io/manual.html#vs-code.

Ran it, but it behaved properly.

Database loaded:     34.60s, 751mb (metadata 5.95s, 4mb; build 18.33s, -12kb)
  item trees: 90
Item Tree Collection: 202.81ms, 5mb
  crates: 15, mods: 91, decls: 1246, bodies: 1187, adts: 128, consts: 84
Item Collection:     96.55s, 827mb
Body lowering:       8.54s, 59mb
  exprs: 44087, ??ty: 17 (0%), ?ty: 14 (0%), !ty: 18
  pats: 8416, ??ty: 11 (0%), ?ty: 0 (0%), !ty: 0
Inference:           73.75s, 549mb
MIR lowering:        4.74s, 25mb
Mir failed bodies: 112 (11%)
Data layouts:        319.16ms, 3392kb
Failed data layouts: 10 (8%)
Const evaluation:    1.37s, 8mb
Failed const evals: 3 (3%)
Total:               185.50s, 1479mb

@NickAcPT
Copy link
Author

NickAcPT commented Dec 8, 2023

@lnicola Would it be helpful with diagnosing the issue for me to setup a dev env for r-a and attempt to git bisect it?
I wasn't able to reproduce it on the latest stable (0.3.1756-standalone (e402c494b 2023-12-01)).

@lnicola
Copy link
Member

lnicola commented Dec 8, 2023

It's almost certainly #15959 (I tested on e0c2754). It would be more helpful to minimize the code that triggers the problem, but it seems very hard. I tried to remove some of the JSON fields and it either doesn't happen or it's less bad, so it's probably not worth it.

EDIT: yup, it's #15959.

@lnicola lnicola added A-macro macro expansion Broken Window Bugs / technical debt to be addressed immediately labels Dec 8, 2023
@lnicola lnicola pinned this issue Dec 8, 2023
@Veykril
Copy link
Member

Veykril commented Dec 8, 2023

Will take a look at that in a bit, very good that this only happens on hover (or possibly other IDE features), we most likely loop indefinitely (while pushing multiple items on the work stack) when trying to downmap tokens in the IDE layer.

@Veykril Veykril self-assigned this Dec 8, 2023
@Veykril
Copy link
Member

Veykril commented Dec 8, 2023

Yep my hunch was right (fwiw I don't even have to do anything, semantic highlighting already triggers this for me)

@Veykril
Copy link
Member

Veykril commented Dec 8, 2023

We are actually just doing an accidental quadratic amount of work. For each token in a macro call we are downmapping we add all relevant tokens in the expansion to the queue. That used to work fine before because relevant was exactly the downmapped tokens for the input token. Things changed now though, we are looking for tokens with a no longer changing span making this quadratic (and serde_json is a tt-muncher so ...). BEcause of lru caching in salsa (our Database) we then start accumulating differing copies of the same expansion because the LRU cache kicks the old result out at some point and recalculates it later again as a separate allocation. We have an additional caching layer in the semantics though which then keeps additional copies around 😅

So, its easy to fix (confirmed already locally), will spend a bit more time on cleaning that part up now though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-macro macro expansion Broken Window Bugs / technical debt to be addressed immediately C-bug Category: bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants