-
-
Notifications
You must be signed in to change notification settings - Fork 371
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
Leaking 10GB memory per minute with wrong type alias def type Foo = Foo
for some ghc versions
#352
Comments
I can reproduce it consistently on my machine, so if there is a good way for me to debug it locally, let me know. |
Thanks for the report, that seems brutal! I just tried the simplest reproduction - create a new buffer, paste that in, toggle to Haskell mode. It uses 20.4Mb for me, with no visible change over 5 minutes. I was using 8.6.5 in VS Code. Therefore, I imagine there's some other factor involved. Did you have that file saved? With a .cabal project? With a .stack project? Or just the raw file? Did you edit it somehow? Did RAM increase even when you were doing nothing? If you kept having to do something, what was it? Is this just the first file you tried, and thus all files are likely buggy? Or has it worked with other files? As for setting a limit, certainly easy to do with the GHC heap settings. But I don't have any idea how to chose a good limit. For a big project I might want to dedicate 100Gb to the IDE. For my home machine, that would kill everything. There's no good solution I can think of... |
Could you share a full project including a |
We have an automated benchmark suite in the ghcide repo which loads a project and runs experiments. The first step would be to set this up as a benchmark that reproduces the leak that you are seeing. |
I can reproduce without having it in a project. Just a bare HS file. Ram usage increases constantly, even when I do nothing. (was over 200GB when I had forgotten about it for a while) I think it might be caused by some impurity, where some remnants of an older version still affects the current version, maybe? |
I'm not entirely sure how I would reproduce it in terms of the benchmark suite's commands |
I have no idea and I have very little time. Without a reproducer that I can run myself, I am unable to help |
just noting that there is something missing from the example: type Parser = Parser Isn't valid. |
I have not yet tested in ghcide HEAD. But the problem is still there when selecting |
Oh, right! That's probably the issue! I was using the |
Maybe it is already fixed on a newer version of
If so, the issue that needs fixing is to place some memory limit so the process can't consume arbitrarily much memory if a similar issue arises. |
Retrie folds can be very memory hungry. I submitted a related PR a few days ago: #321 To be sure, try to repro with the retrie command line tool |
To clarify, it wasn't retrie that caused the memory leak, it was retire that caused my code to have an infinite type alias loop, which in turn triggered the unbounded memory usage in ghcide. |
Is that a theory or something you have confirmed beyond doubt? |
But how does |
I know beyond doubt that retire has nothing to do with it, since it triggers without using retrie at all, from just opening a file with the content above (with just ghcide, no HLS extensions). |
Now I know beyond doubt. This file is a minimal reproducing example:
|
I just reproduced - seems we have a bug that we don't check files which are not yet saved which meant my test wasn't valid. To reproduce:
For me, Windows, VS Code, GHC 8.6.5, it sits at 1 CPU working full trottle. Memory is increasing (currently 2Gb after 2 mins). So confirmed, and very serious! |
I was also able to reproduce by running
in a terminal. |
Very cool, I can repro this too |
Bisected it back to 373c406 * Multi Component (#522) |
Seems like the issue occurs in a call to |
This simple ghc-api program fails to reproduce import GHC
main = runGhc (Just "***libdir***") $ do
addTarget $ Target (TargetFile "mem.hs" Nothing) False Nothing
mg <- depanal [] False
let [ms] = mgModSummaries mg
pm <- parseModule ms
tm <- typecheckModule pm
return ()
|
I don't think it gets to typechecking @wz1000. I can confirm as @pepeiborra said, it happened with the multi-component commit. The reason is if you go back to multi-component (373c406), then one commit behind it to 51907fe and run ghcide you'll see: [cody@nixos:/tmp/blah]$ /nix/store/7fii3y3a981cpsc2lcah0vaynrnd57ky-ghcide-exe-ghcide-0.1.0/bin//ghcide
ghcide version: 0.1.0 (GHC: 8.8.4) (PATH: /nix/store/7fii3y3a981cpsc2lcah0vaynrnd57ky-ghcide-exe-ghcide-0.1.0/bin/ghcide)
Ghcide setup tester in /tmp/blah.
Report bugs at https://github.com/digital-asset/ghcide/issues
Step 1/6: Finding files to test in /tmp/blah
Found 1 files
Step 2/6: Looking for hie.yaml files that control setup
Found 1 cradle
Step 3/6, Cradle 1/1: Implicit cradle for /tmp/blah
Cradle {cradleRootDir = "/tmp/blah", cradleOptsProg = CradleAction: Default}
Step 4/6, Cradle 1/1: Loading GHC Session
Interface files cache dir: /home/cody/.cache/ghcide/da39a3ee5e6b4b0d3255bfef95601890afd80709
Step 5/6: Initializing the IDE
Step 6/6: Type checking the files
File: /tmp/blah/Bug.hs
Hidden: no
Range: 1:0-1:14
Source: typecheck
Severity: DsError
Message: Cycle in type synonym declarations:/tmp/blah/Bug.hs:1:1-14: type Foo = Foo
Files that failed:
* /tmp/blah/Bug.hs
Completed (0 files worked, 1 file failed) Where type-checking shows there is a cycle. If you go back to 373c406 though it never gets passed log message [cody@nixos:/tmp/blah]$ /nix/store/hqgl28vs5kjyl18bjjh0gqv40b4r0288-ghcide-exe-ghcide-0.1.0/bin/ghcide
ghcide version: 0.1.0 (GHC: 8.8.4) (PATH: /nix/store/hqgl28vs5kjyl18bjjh0gqv40b4r0288-ghcide-exe-ghcide-0.1.0/bin/ghcide)
Ghcide setup tester in /tmp/blah.
Report bugs at https://github.com/digital-asset/ghcide/issues
Step 1/4: Finding files to test in /tmp/blah
Found 1 files
Step 2/4: Looking for hie.yaml files that control setup
Found 1 cradle
Step 3/4: Initializing the IDE
Step 4/4: Type checking the files
[INFO] Consulting the cradle for "/tmp/blah/Bug.hs"
[INFO] Using interface files cache dir: /home/cody/.cache/ghcide/main-da39a3ee5e6b4b0d3255bfef95601890afd80709
[INFO] Making new HscEnv[main]
C-c C-c |
To be more specific, this is the last line that gets logged: https://github.com/codygman/ghcide/blob/cc287b6e3a532499b35845e189c987ce79394f49/exe/Main.hs#L351 This is when the |
I was led to newComponentCache which has a comment eerily close to our scenario 😆 logDebug logger ("New Component Cache HscEnvEq: " <> T.pack (show res))
let is = importPaths df
ctargets <- concatMapM (targetToFile is . targetId) (componentTargets ci)
-- A special target for the file which caused this wonderful
-- component to be created. In case the cradle doesn't list all the targets for
-- the component, in which case things will be horribly broken anyway.
-- Otherwise, we will immediately attempt to reload this module which
-- **causes an infinite loop and high CPU usage**. <============= this one right here
let special_target = (componentFP ci, res)
let xs = map (,res) ctargets
return (special_target:xs, res) |
So apparently the component dynamic flags being updated causes this? A minimum change to trigger things is removing that piece in: newComponentCache logger hsc_env uids ci = do
let df = componentDynFlags ci
let hscEnv' = hsc_env -- Does not allocate GBs of ram
let hscEnv' = hsc_env { hsc_dflags = df } -- allocates GBs of ram That is, don't do the record update and you'll get the pre multli-component behavior where tyepchecking happens and says "cycle in type synonym declarations". I don't know enough about the underlying pieces such as DynFlags to understand this better yet. |
Could |
According to the comment, not evaluation but a cache fail causes the high CPU usage, e.g. ghcide is not aware of the target that it just tried to load. So, I doubt that |
Does the problem go away with a proper hie.yaml file that declares all the targets? One way to check that is create a Cabal project with this module alone, and use a Cabal cradle. |
I can't reproduce with a cabal project in this format:
So multi-component breaks in the case of a bare file without a project or hie.yaml. Maybe adding a direct cradle fixes it? Can anyone explain why exactly this is? I'm very interested in knowing and will continue figuring it out on my own regardless, but I bet someone can weigh in more here. |
Já foi resolvido? Estou com o mesmo problema no ubuntu 20.04 quando abro arquivos haskell no vs code |
This would need a issue in ghcide |
- Redundant "All" imports, e.g. Maybe(..) - Redundant datatype plus constructors, e.g. Maybe(Just) Fixes #352
I tried it on a recent version of hls and it returns
now. If there is also a test case for this (with a timeout, so a regression wouldn't hang ci) we can probably close this now. Edit: Or maybe it is only fixed on recent ghc versions? I didn't check. |
type Foo = Foo
type Foo = Foo
type Foo = Foo
for some ghc versions
Opening this file in vs code
causes HLS to consume a lot of ram quickly. This is the result after just a few minutes of having the file open.
Log
Regardless of if this specific bug is fixed, we should probably add some limit, so HLS won't consume all available memory on the system when problems arise.
The text was updated successfully, but these errors were encountered: