zed-industries / zed

Code at the speed of thought – Zed is a high-performance, multiplayer code editor from the creators of Atom and Tree-sitter.
https://zed.dev
Other
50.52k stars 3.13k forks source link

Massive memory spike sometimes on a Rust project #8436

Open PgBiel opened 9 months ago

PgBiel commented 9 months ago

Check for existing issues

Describe the bug / provide steps to reproduce it

Hi, I sometimes get a very nasty memory leak / spike while I'm working on a Rust project. When it is triggered, memory usage is filled very quickly; Zed can reach 40 GB of memory consumption within a few minutes before requiring a force quit (Zed is completely frozen since the beginning of the leak, with high CPU usage). Not sure what causes it yet; last time it was after selecting a block of code, at least. Worth mentioning that it is a relatively large Rust project.

I've attached some logs from around the moment of the latest leak. I was told to share the memory usage of rust-analyzer at the time of the leak. On the latest one, I believe it was Zed using up all the memory, not rust-analyzer itself, but I'll try to confirm this (and/or gather further details) if it happens again.

Environment

Zed: v0.123.6 (Zed) OS: macOS 13.0.1 Memory: 8 GiB Architecture: aarch64

If applicable, add mockups / screenshots to help explain present your vision of the feature

No response

If applicable, attach your ~/Library/Logs/Zed/Zed.log file to this issue.

If you only need the most recent lines, you can run the zed: open log command palette action to see the last 1000.

Possibly related errors in the logs

``` 2024-02-26T01:09:46-03:00 [WARN] Generic lsp request to rust-analyzer failed: Invalid Range [... line above is repeated tens of times, repetitions omitted ...] 2024-02-26T01:09:46-03:00 [WARN] Generic lsp request to rust-analyzer failed: Invalid Range 2024-02-26T01:09:46-03:00 [WARN] Generic lsp request to rust-analyzer failed: Invalid Range 2024-02-26T01:09:46-03:00 [ERROR] inlay hint update task for range Anchor { timestamp: Lamport {0: 819}, offset: 0, bias: Right, buffer_id: Some(BufferId(2)) }..Anchor { timestamp: Lamport {0: 727}, offset: 4, bias: Right, buffer_id: Some(BufferId(2)) } failed: inlay hint fetch task: inlay hints LSP request: Invalid Range 2024-02-26T01:09:46-03:00 [ERROR] inlay hint update task for range Anchor { timestamp: Lamport {0: 819}, offset: 0, bias: Right, buffer_id: Some(BufferId(2)) }..Anchor { timestamp: Lamport {0: 969}, offset: 188, bias: Right, buffer_id: Some(BufferId(2)) } failed: inlay hint fetch task: inlay hints LSP request: Invalid Range 2024-02-26T01:09:46-03:00 [ERROR] inlay hint update task for range Anchor { timestamp: Lamport {0: 819}, offset: 0, bias: Right, buffer_id: Some(BufferId(2)) }..Anchor { timestamp: Lamport {0: 727}, offset: 4, bias: Right, buffer_id: Some(BufferId(2)) } failed: inlay hint fetch task: inlay hints LSP request: Invalid Range 2024-02-26T01:09:46-03:00 [ERROR] inlay hint update task for range Anchor { timestamp: Lamport {0: 819}, offset: 0, bias: Right, buffer_id: Some(BufferId(2)) }..Anchor { timestamp: Lamport {0: 727}, offset: 4, bias: Right, buffer_id: Some(BufferId(2)) } failed: inlay hint fetch task: inlay hints LSP request: Invalid Range 2024-02-26T01:09:46-03:00 [ERROR] inlay hint update task for range Anchor { timestamp: Lamport {0: 819}, offset: 0, bias: Right, buffer_id: Some(BufferId(2)) }..Anchor { timestamp: Lamport {0: 727}, offset: 4, bias: Right, buffer_id: Some(BufferId(2)) } failed: inlay hint fetch task: inlay hints LSP request: Invalid Range 2024-02-26T01:09:46-03:00 [ERROR] inlay hint update task for range Anchor { timestamp: Lamport {0: 819}, offset: 0, bias: Right, buffer_id: Some(BufferId(2)) }..Anchor { timestamp: Lamport {0: 969}, offset: 188, bias: Right, buffer_id: Some(BufferId(2)) } failed: inlay hint fetch task: inlay hints LSP request: Invalid Range 2024-02-26T01:09:46-03:00 [ERROR] inlay hint update task for range Anchor { timestamp: Lamport {0: 819}, offset: 0, bias: Right, buffer_id: Some(BufferId(2)) }..Anchor { timestamp: Lamport {0: 727}, offset: 4, bias: Right, buffer_id: Some(BufferId(2)) } failed: inlay hint fetch task: inlay hints LSP request: Invalid Range 2024-02-26T01:09:46-03:00 [ERROR] inlay hint update task for range Anchor { timestamp: Lamport {0: 819}, offset: 0, bias: Right, buffer_id: Some(BufferId(2)) }..Anchor { timestamp: Lamport {0: 969}, offset: 188, bias: Right, buffer_id: Some(BufferId(2)) } failed: inlay hint fetch task: inlay hints LSP request: Invalid Range 2024-02-26T01:09:46-03:00 [ERROR] inlay hint update task for range Anchor { timestamp: Lamport {0: 819}, offset: 0, bias: Right, buffer_id: Some(BufferId(2)) }..Anchor { timestamp: Lamport {0: 727}, offset: 4, bias: Right, buffer_id: Some(BufferId(2)) } failed: inlay hint fetch task: inlay hints LSP request: Invalid Range 2024-02-26T01:09:46-03:00 [ERROR] inlay hint update task for range Anchor { timestamp: Lamport {0: 819}, offset: 0, bias: Right, buffer_id: Some(BufferId(2)) }..Anchor { timestamp: Lamport {0: 727}, offset: 4, bias: Right, buffer_id: Some(BufferId(2)) } failed: inlay hint fetch task: inlay hints LSP request: Invalid Range 2024-02-26T01:09:46-03:00 [ERROR] inlay hint update task for range Anchor { timestamp: Lamport {0: 819}, offset: 0, bias: Right, buffer_id: Some(BufferId(2)) }..Anchor { timestamp: Lamport {0: 727}, offset: 4, bias: Right, buffer_id: Some(BufferId(2)) } failed: inlay hint fetch task: inlay hints LSP request: Invalid Range 2024-02-26T01:09:46-03:00 [ERROR] inlay hint update task for range Anchor { timestamp: Lamport {0: 819}, offset: 0, bias: Right, buffer_id: Some(BufferId(2)) }..Anchor { timestamp: Lamport {0: 727}, offset: 4, bias: Right, buffer_id: Some(BufferId(2)) } failed: inlay hint fetch task: inlay hints LSP request: Invalid Range 2024-02-26T01:09:46-03:00 [ERROR] inlay hint update task for range Anchor { timestamp: Lamport {0: 819}, offset: 0, bias: Right, buffer_id: Some(BufferId(2)) }..Anchor { timestamp: Lamport {0: 727}, offset: 4, bias: Right, buffer_id: Some(BufferId(2)) } failed: inlay hint fetch task: inlay hints LSP request: Invalid Range 2024-02-26T01:09:46-03:00 [ERROR] inlay hint update task for range Anchor { timestamp: Lamport {0: 819}, offset: 0, bias: Right, buffer_id: Some(BufferId(2)) }..Anchor { timestamp: Lamport {0: 727}, offset: 4, bias: Right, buffer_id: Some(BufferId(2)) } failed: inlay hint fetch task: inlay hints LSP request: Invalid Range 2024-02-26T01:09:46-03:00 [ERROR] inlay hint update task for range Anchor { timestamp: Lamport {0: 819}, offset: 0, bias: Right, buffer_id: Some(BufferId(2)) }..Anchor { timestamp: Lamport {0: 727}, offset: 4, bias: Right, buffer_id: Some(BufferId(2)) } failed: inlay hint fetch task: inlay hints LSP request: Invalid Range 2024-02-26T01:09:46-03:00 [ERROR] inlay hint update task for range Anchor { timestamp: Lamport {0: 819}, offset: 0, bias: Right, buffer_id: Some(BufferId(2)) }..Anchor { timestamp: Lamport {0: 969}, offset: 188, bias: Right, buffer_id: Some(BufferId(2)) } failed: inlay hint fetch task: inlay hints LSP request: Invalid Range 2024-02-26T01:09:46-03:00 [ERROR] inlay hint update task for range Anchor { timestamp: Lamport {0: 819}, offset: 0, bias: Right, buffer_id: Some(BufferId(2)) }..Anchor { timestamp: Lamport {0: 727}, offset: 4, bias: Right, buffer_id: Some(BufferId(2)) } failed: inlay hint fetch task: inlay hints LSP request: Invalid Range 2024-02-26T01:09:46-03:00 [ERROR] inlay hint update task for range Anchor { timestamp: Lamport {0: 819}, offset: 0, bias: Right, buffer_id: Some(BufferId(2)) }..Anchor { timestamp: Lamport {0: 969}, offset: 188, bias: Right, buffer_id: Some(BufferId(2)) } failed: inlay hint fetch task: inlay hints LSP request: Invalid Range 2024-02-26T01:09:46-03:00 [ERROR] inlay hint update task for range Anchor { timestamp: Lamport {0: 819}, offset: 0, bias: Right, buffer_id: Some(BufferId(2)) }..Anchor { timestamp: Lamport {0: 727}, offset: 4, bias: Right, buffer_id: Some(BufferId(2)) } failed: inlay hint fetch task: inlay hints LSP request: Invalid Range 2024-02-26T01:09:46-03:00 [ERROR] inlay hint update task for range Anchor { timestamp: Lamport {0: 819}, offset: 0, bias: Right, buffer_id: Some(BufferId(2)) }..Anchor { timestamp: Lamport {0: 727}, offset: 4, bias: Right, buffer_id: Some(BufferId(2)) } failed: inlay hint fetch task: inlay hints LSP request: Invalid Range 2024-02-26T01:09:46-03:00 [ERROR] inlay hint update task for range Anchor { timestamp: Lamport {0: 819}, offset: 0, bias: Right, buffer_id: Some(BufferId(2)) }..Anchor { timestamp: Lamport {0: 727}, offset: 4, bias: Right, buffer_id: Some(BufferId(2)) } failed: inlay hint fetch task: inlay hints LSP request: Invalid Range 2024-02-26T01:09:46-03:00 [ERROR] inlay hint update task for range Anchor { timestamp: Lamport {0: 819}, offset: 0, bias: Right, buffer_id: Some(BufferId(2)) }..Anchor { timestamp: Lamport {0: 969}, offset: 188, bias: Right, buffer_id: Some(BufferId(2)) } failed: inlay hint fetch task: inlay hints LSP request: Invalid Range 2024-02-26T01:09:46-03:00 [ERROR] inlay hint update task for range Anchor { timestamp: Lamport {0: 819}, offset: 0, bias: Right, buffer_id: Some(BufferId(2)) }..Anchor { timestamp: Lamport {0: 727}, offset: 4, bias: Right, buffer_id: Some(BufferId(2)) } failed: inlay hint fetch task: inlay hints LSP request: Invalid Range 2024-02-26T01:09:46-03:00 [ERROR] inlay hint update task for range Anchor { timestamp: Lamport {0: 819}, offset: 0, bias: Right, buffer_id: Some(BufferId(2)) }..Anchor { timestamp: Lamport {0: 969}, offset: 188, bias: Right, buffer_id: Some(BufferId(2)) } failed: inlay hint fetch task: inlay hints LSP request: Invalid Range 2024-02-26T01:09:46-03:00 [ERROR] inlay hint update task for range Anchor { timestamp: Lamport {0: 819}, offset: 0, bias: Right, buffer_id: Some(BufferId(2)) }..Anchor { timestamp: Lamport {0: 727}, offset: 4, bias: Right, buffer_id: Some(BufferId(2)) } failed: inlay hint fetch task: inlay hints LSP request: Invalid Range 2024-02-26T01:09:46-03:00 [ERROR] inlay hint update task for range Anchor { timestamp: Lamport {0: 819}, offset: 0, bias: Right, buffer_id: Some(BufferId(2)) }..Anchor { timestamp: Lamport {0: 727}, offset: 4, bias: Right, buffer_id: Some(BufferId(2)) } failed: inlay hint fetch task: inlay hints LSP request: Invalid Range 2024-02-26T01:09:46-03:00 [ERROR] inlay hint update task for range Anchor { timestamp: Lamport {0: 819}, offset: 0, bias: Right, buffer_id: Some(BufferId(2)) }..Anchor { timestamp: Lamport {0: 727}, offset: 4, bias: Right, buffer_id: Some(BufferId(2)) } failed: inlay hint fetch task: inlay hints LSP request: Invalid Range 2024-02-26T01:09:46-03:00 [ERROR] inlay hint update task for range Anchor { timestamp: Lamport {0: 819}, offset: 0, bias: Right, buffer_id: Some(BufferId(2)) }..Anchor { timestamp: Lamport {0: 727}, offset: 4, bias: Right, buffer_id: Some(BufferId(2)) } failed: inlay hint fetch task: inlay hints LSP request: Invalid Range 2024-02-26T01:09:47-03:00 [ERROR] inlay hint update task for range Anchor { timestamp: Lamport {0: 819}, offset: 0, bias: Right, buffer_id: Some(BufferId(2)) }..Anchor { timestamp: Lamport {0: 727}, offset: 4, bias: Right, buffer_id: Some(BufferId(2)) } failed: inlay hint fetch task: inlay hints LSP request: Invalid Range 2024-02-26T01:09:48-03:00 [ERROR] inlay hint update task for range Anchor { timestamp: Lamport {0: 819}, offset: 0, bias: Right, buffer_id: Some(BufferId(2)) }..Anchor { timestamp: Lamport {0: 727}, offset: 4, bias: Right, buffer_id: Some(BufferId(2)) } failed: inlay hint fetch task: inlay hints LSP request: Invalid Range 2024-02-26T01:09:51-03:00 [ERROR] inlay hint update task for range Anchor { timestamp: Lamport {0: 819}, offset: 0, bias: Right, buffer_id: Some(BufferId(2)) }..Anchor { timestamp: Lamport {0: 727}, offset: 4, bias: Right, buffer_id: Some(BufferId(2)) } failed: inlay hint fetch task: inlay hints LSP request: Invalid Range 2024-02-26T01:09:56-03:00 [WARN] request completed with error: request or operation took longer than the configured timeout time 2024-02-26T01:09:56-03:00 [ERROR] crates/client/src/telemetry.rs:583: request or operation took longer than the configured timeout time Caused by: [28] Timeout was reached 2024-02-26T01:09:57-03:00 [ERROR] inlay hint update task for range Anchor { timestamp: Lamport {0: 819}, offset: 0, bias: Right, buffer_id: Some(BufferId(2)) }..Anchor { timestamp: Lamport {0: 727}, offset: 4, bias: Right, buffer_id: Some(BufferId(2)) } failed: inlay hint fetch task: inlay hints LSP request: Invalid Range ```

jnathanh commented 9 months ago

Not sure if this is the same memory issue, but I also ran into a memory spike issue. Was trying the editor for the first time and was curious how it would handle opening a large file (1.8 GB json). The app quickly froze up and stopped responding, was using at least 17GB memory, and eventually crashed the OS (I'm on an 8GB system).

I generated the file with this script

object_size=12
num_objects=$((1024*1024*1024 / $object_size))
output_file=~/Downloads/output.json
{
  printf "[\n"
  for ((i=1; i<num_objects; i++)); do
    printf "{\"data\": \"%d\"},\n" "$i"
  done
  printf "{}\n"
  printf "]\n"
} > "$output_file"
Screenshot 2024-02-27 at 6 36 46 PM
mrnugget commented 8 months ago

@PgBiel do you have Xcode and could record a profile of when that happens? It's really hard to get to the bottom of this without circling in on when exactly it happens.

Your logs make it sound like you do have inlay hints enabled when that happens though — is that correct?

@jnathanh I think your issue is "unrelated" to the specifics of this one here, can you open another ticket?

PgBiel commented 8 months ago

@PgBiel do you have Xcode and could record a profile of when that happens? It's really hard to get to the bottom of this without circling in on when exactly it happens.

I don't have Xcode, but I'll keep that in mind next time. Unfortunately, I am now on a Linux PC so I won't be able to provide further info for now (sorry!), but I hope someone with a similar problem manages to bring some more useful info to the table.

For reference, though, I was editing the Typst codebase (at https://github.com/typst/typst).

Your logs make it sound like you do have inlay hints enabled when that happens though — is that correct?

Yes (they're always enabled).

mrnugget commented 8 months ago

For reference, though, I was editing the Typst codebase (at https://github.com/typst/typst).

Great! That's fantastic to know. Anything specific you did there? Any file you had open that triggered this?

mrnugget commented 8 months ago

Cloned, built, and opened typst/typst in Zed (current version from main) and opened a few of the longest files: typst-syntax/src/ast.rs, typst/src/visualize/color.rs. With and without inlay hints I can't detect any excessive memory consumption. (I did notice some stuttering when scrolling, which I want to look into)

Zed: 512mb rust-analyzer: 1GB

jnathanh commented 8 months ago

@jnathanh I think your issue is "unrelated" to the specifics of this one here, can you open another ticket?

opened a new issue: https://github.com/zed-industries/zed/issues/8680

PgBiel commented 8 months ago

For reference, though, I was editing the Typst codebase (at https://github.com/typst/typst).

Great! That's fantastic to know. Anything specific you did there? Any file you had open that triggered this?

I believe I was editing the files under crates/typst/src/layout/grid (on the latest main commit - before, they were in my own branch).

During the latest spike, I had opened a { } block after an if condition when it froze and started using up all memory.

JosephTLyons commented 8 months ago

This memory leak has been a long-standing issue that we've tried to fix multiple times - unfortunately, we can't seem to find concrete steps to reproducing it.

mocenigo commented 8 months ago

I am having the same problem, which sadly makes zed useless for now (it is very nice and promising though). I load a large file, say, 130Mb of text, and at some point the memory starts ballooning. It usually starts to increase after a save operation. Then in Activity Monitor I quickly see that it is using 2.6Gb, then 4.1, then 8, then 13Gb... It is like some structure is constantly doubling.

mocenigo commented 8 months ago

BTW @mrnugget , I have XCode and have built Zed in debug mode. How do I capture a profile?

mrnugget commented 8 months ago

@mocenigo thank you! That'd be fantastic if you can reproduce it. If you can reliably reproduce it with a specific file and you can share it, you can also email it to me and I'll try.

But here's a video of how to capture memory allocations for a debug build using Instruments.app:

https://github.com/zed-industries/zed/assets/1185253/b91e5cf6-c3f7-433c-a194-3b10c5f15889

mrnugget commented 7 months ago

I looked into this today, using the profiles that @mocenigo sent me, along with the *.tex file they used.

I can't reproduce the issue without the zed-latex extension. I don't get any memory leaks. If I install the extension though and open the file, I get massive memory leaks. The profile shows tree-sitter calls, so I suspect that something is off with the tex tree-sitter grammar. It's not the extension itself, since the memory leak even shows up when I comment out everything in the extension and rebuild it locally.

That doesn't explain the problem with memory spikes in Rust problems. It makes me wonder whether the memory spike some of you are seeing isn't a pathological case for some tree-sitter grammars/parsers.

mrnugget commented 7 months ago

@PgBiel I checked out the typst codebase again, clicked around, opened a bunch of files, open crates/typst/src/layout/grid/layout.rs, made some changes in there — I can't get it to leak memory. Memory consumption might go up, but it also goes down again, quickly.

Can you reliably reproduce it?

PgBiel commented 7 months ago

Hey @mrnugget. Unfortunately I don't have a reliable way to reproduce it, and it's been a while since I've last tested it (and even more so experienced it). I'll let you know if I face this problem again, hopefully with more details.

In the meantime, feel free to close the issue if that is appropriate.

mocenigo commented 7 months ago

I looked into this today, using the profiles that @mocenigo sent me, along with the *.tex file they used.

I can't reproduce the issue without the zed-latex extension. I don't get any memory leaks. If I install the extension though and open the file, I get massive memory leaks. The profile shows tree-sitter calls, so I suspect that something is off with the tex tree-sitter grammar. It's not the extension itself, since the memory leak even shows up when I comment out everything in the extension and rebuild it locally.

That doesn't explain the problem with memory spikes in Rust problems. It makes me wonder whether the memory spike some of you are seeing isn't a pathological case for some tree-sitter grammars/parsers.

I strongly believe that there is at least one issue here.

If you open a very large file, and perform some edits, you will see the memory usage spike, as if large structures are copied but never released. I understand for instance the existende of undo buffers. But, if you append a whole copy of the original text to itself, and the text is 130Mb, the memory consumption should not go up by 2Gb. While I understand that you may have GPUI buffers around, you do not need to keep them for UNDOs. This issues is probably independent of file size, but it is easier to observe with large ones.

Then, if you close the window, the memory does NOT go down. It is not released.

In other words, Zed does not free memory properly.

Therefore, if you close this particular issue, please open one about failed memory release.

mrnugget commented 7 months ago

@mocenigo take a look at this: https://github.com/zed-industries/zed/pull/10321

I think one half of what you're seeing is what this PR addresses (high memory usage) and the other part might be MiMalloc, which is very aggressive in my tests when it comes to allocating memory.

LuarRaNa commented 7 months ago

Hello... I have witnessed the problem when using Zed terminal and using Lazygit for all operations that have to do with Git. What I have noticed is that when switching branches the ram consumption in Zed increases. The branches diverge too much and using the time command, it gives the following:

time git checkout develop
1.55 real         0.37 user         1.17 sys

Other information: PHP project No opened files.

mrnugget commented 7 months ago

@LuarRaNa can you create a separate ticket for this with exact steps to reproduce?

chibuzoro-salesfloor commented 2 months ago

I open a few rust files, and terminal. Do nothing, wait an hour or two, operating system runs out of memory. Culprit Zed with over 40gb consumed. Zed version: 0.152.4 MacOS: Sonoma Aarc: Intel/Amd64

mrnugget commented 2 months ago

@chibuzoro-salesfloor is this easy to reproduce with an example project? i.e. does it happen if you open some files in https://github.com/BurntSushi/ripgrep?