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

memory leak #96

Open
gelisam opened this issue Apr 22, 2020 · 12 comments
Open

memory leak #96

gelisam opened this issue Apr 22, 2020 · 12 comments
Labels

Comments

@gelisam
Copy link
Contributor

gelisam commented Apr 22, 2020

Even a simple pure () uses more and more memory (on ghc-8.6.5, about 4 Kb per loop):

import Control.Monad
import GHC.Stats
import Language.Haskell.Interpreter
import System.Mem

printMemoryConsumption :: IO ()
printMemoryConsumption = do
  performGC
  live_bytes <- gcdetails_live_bytes . gc <$> getRTSStats
  putStrLn $ show live_bytes ++ " bytes"

main :: IO ()
main = forever $ do
  runInterpreter $ pure ()
  printMemoryConsumption
@gelisam
Copy link
Contributor Author

gelisam commented Apr 22, 2020

The good news is that the size of the leak does not appear to be significantly bigger if we interpret a computation which allocates a lot of memory.

@gelisam
Copy link
Contributor Author

gelisam commented Apr 22, 2020

It gets bigger if we call eval often though.

@gelisam gelisam added the bug label Apr 25, 2020
@ghost
Copy link

ghost commented Aug 4, 2020

@gelisam Can this be used in production?

The problem I am tackling is:

I need an interpreter/compiler that can be run as a microservice. The microservice will execute a one liner lambda expression with provided inputs(from external users) and return the result, in some sandboxed way.

I was thinking of using Hint + HaXR for this, can you please advise if Hint(current or past version) can be used for this?

@KiaraGrouwstra
Copy link
Collaborator

KiaraGrouwstra commented Aug 7, 2020

hm, I may have run into this as well.

I'm using hint for neural program synthesis, so basically I've been calling it a lot.

@gelisam
Copy link
Contributor Author

gelisam commented Aug 8, 2020

@gelisam Can this be used in production?

I don't like the question. This is an old, stable codebase which has been passed on from maintainer to maintainer for years. But I do not offer paid support, and as per the license, I offer no warranty of merchantability or fitness for a particular purpose. I am not aware of any significant flaw which would cause me to advise you against using it in production, but if you do and something breaks in production, it is your responsibility, not mine.

@ghost
Copy link

ghost commented Aug 8, 2020

Thanks for clearing things, its nice of you to maintain this library. For now, we have decided to create our own Lisp dialect, which will do for our use case.

@gelisam
Copy link
Contributor Author

gelisam commented Aug 8, 2020

I have isolated the source of the leak to the installSupportModule function: if I comment everything in initialize except it, the leak remains, whereas if I comment it and keep everything else, theleak disappears.

@gelisam
Copy link
Contributor Author

gelisam commented Aug 8, 2020

I made some progress, but I now think I have to start over.

By continuing to comment out more and more code, I have reduced the example program to one which does not use hint anymore, only the ghc library:

import Control.Monad
import GHC.Stats
import System.Mem
import qualified GHC
import qualified GHC.Paths

printMemoryConsumption :: IO ()
printMemoryConsumption = do
  performGC
  live_bytes <- gcdetails_live_bytes . gc <$> getRTSStats
  putStrLn $ show live_bytes ++ " bytes"

main :: IO ()
main = do
  forever $ do
    GHC.runGhcT (Just GHC.Paths.libdir) $ do
      GHC.load (GHC.LoadUpTo (GHC.mkModuleName "invalid module name"))
    printMemoryConsumption

So, the next step is to report this space leak upstream to the ghc team, right? Well, not so fast. The ghc team knows that ghc has space leaks, and they are focusing their efforts on their largest leaks. Is the one we found a large leak? Let's see... no, only 64 bytes per loop. Since the original program was leaking 4 kb per loop, the main source of the leak is elsewhere.

@gelisam
Copy link
Contributor Author

gelisam commented Aug 9, 2020

The amount of memory leaked each loop goes up when I add a bunch of redundant id calls to the phantom file, but it does not (in fact it even goes down??) when I add a bunch of comments. It thus isn't the string itself which is leaking that memory, it is ghc's parsed representation. so if that's the leak, then the problem isn't the usual space leak in which we're holding to some thunk or some data structure, it's either a leak in the ghc library, or hint's cleanPhantomModules is not calling the right ghc functions to tell the ghc library to release the module.

@gelisam
Copy link
Contributor Author

gelisam commented Aug 9, 2020

Hmm, it also goes up when I make the module smaller; that pretty much invalidates my hypothesis. I think the longer and shorter modules are probably both invalid Haskell, my test harness isn't printing exceptions, and the exceptional path is leaking a lot more memory than the happy path.

@markusschlegel
Copy link

Are there any updates on this issue? I ran the experiment above with GHC 9.2 and Hint 0.9.0.6 and the leak is still present. It leaks about 800 bytes per iteration on my machine.

@gelisam
Copy link
Contributor Author

gelisam commented May 12, 2023

This is not a priority for me at the moment. Would you like to take a look? Hint needs more volunteers!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants