The following script spawns ghci, and that spawned ghci then goes on to leak memory:
importControl.ConcurrentimportControl.MonadimportSystem.IOimportSystem.Processmain=do(Justhin,Nothing,Nothing,pid)<-createProcess(proc"ghci"["+RTS","-S"]){std_in=CreatePipe}forever$dothreadDelay100000-- 0.1shPutStrLnhin"\"this is a test of outputting stuff\""hFlushhin
This script just writes a string to GHCi, which then echos it back. The +RTS -S is useful to watch the live memory tick up in realtime, but it leaks without it, and the leak can be seen in process explorer (87Mb to 700Mb over about 30 minutes).
While repeatedly writing commands may not be a standard usage of ghci, it is when driven by tools such as ghcid (https://hackage.haskell.org/package/ghcid) and other IDE-like uses.
Trac metadata
Trac field
Value
Version
8.2.1
Type
Bug
TypeOfFailure
OtherFailure
Priority
normal
Resolution
Unresolved
Component
GHCi
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Child items
0
Show closed items
No child items are currently assigned. Use child items to break down this issue into smaller parts.
Linked items
0
Link issues together to show that they're related or that one is blocking others.
Learn more.
Hmm I believe this is not Windows specific, peaking into the heap it seems to be all PAPs and closures so I believe it's a generic GHCi bug, where a reference is being held to the previous repl results and so preventing GC.
I'll find some time to take a look at it, thanks for the report!
I can confirm that this occurs in GHCi, Intero, and HIE on Mac OSX. Someone suggested :set +r could solve this, but it doesn't seem to help. However, :set -fobject-code *seems* to either slow-down the memory leak or stop it altogether.
Just to be clear, I should be looking at the third column increasing? It starts out for me at around 8,569,448 and gradually increases up to
13,360,528 after running 1000 iterations.
Other things I tried.
Not creating it bindings as one was created for each line. This didn't seem to make a big difference for small examples but does for big examples. (Max residency 12mb (unmod) vs 13mb (mod))
Not running any Haskell code, so changing the string line to `:set -XTypeApplications", the live column still increased but more slowly. (Up to 11219144 after 1000 iterations).
Running with :set -fobject-code, seemed to make no difference or make things slightly worse (14051160) (Just once at the start of the loop).
Increasing the size of the string (by 100x) makes things much worse 62235312 but not 100x worse, just 6x worse, maximum residency 55mb. BUT, running with my modified compiler which doesn't generate it bindings, only 13mb max residency.
Anyway I don't really know what I am looking for so if someone could point out which number I should be looking at and what it means for my hardware averse brain it would be useful.
30000 iterations of :set -XTypeApplications only leads to 16mb of maximum residency so perhaps there is no serious leak there. (6mb with 1000 iterations)
The end thing that matters is process memory usage, and given enough time (half an hour or so) that clearly increases, but not linearly (thanks to effects like GC). The use of the RTS columns just gives you an easy way to spot it faster. The columns for the RTS stats are:
Alloc Copied Live GC GC TOT TOT Page Flts bytes bytes bytes user elap user elap
Of those, Live bytes is the one I was watching (3rd one along)
Doing 1000 iterations with a very big string (approx 20000 chars) results in 47mb max residency with no_it. Doing 1000 iterations with a vanilla compiler causes my computer to oom, 100 iterations requires 488mb
Passing -fno-it causes () to be printed to stdout vastly more often. Did this also break that bit? Looking at the section on GHCi Plans I note that the no-it branch is missing the it::() check in step A.
Anything that wraps ghci into a program that users are still expected to interact with is going to start having weird special cases to undo these changes. For my specific case of ghcid I can remove the () when ghcid itself sends a command in (no real problem), but I also allow the user to interact with the underlying ghci (via the --test flag), and there the surprising change in behaviour is going to be unpleasant and hard to avoid without just filtering out () lines, some of which might be deliberate.
Any chance of getting the behaviour to omit () added back?
Any chance of getting the behaviour to omit () added back?
This doesn't seem to have much to do with the Description!
I have no idea what the old behaviour is, what the new behaviour is, or which patch made the change that you object to.
Would you like give a short ab-initio specification of the change you want? It does not sound controversial or hard to implement. Maybe you can offer a patch too?
If this ever makes it into a released GHC (which it will with GHC 8.6) then I need to adjust ghcid to cope with it. Once I've done that, changing the behaviour for a future release has very little benefit to me. As a result, closing this ticket with Fixed as the initial ticket was fixed.