Skip to content

Memory Leak with GHC 9.4.7

Summary

Hello, we have a web service running on a machine and the memory usage increase over multiple days:

(The times were the memory usage goes down is when it is restarted during an update. image

However, the live memory and the compact regions are using a fixed amount of memory: image image

I know that the problem has existed for months but I am don't know when it started.

The server is written using servant and Warp.

Steps to reproduce

I can't share the code but I have tracked the problem quite a bit.

I have tracked down the problem to a endpoint that writes data from the db to disk. It is called every 4 hours.

If I only get the data from the db it desn't leak.

By doing the request in a loop I get an increase in memory use of multiple GB.

The code that leak looks like that:

  let f data = do
        let bs = getjson data
            fp = getFilepath data
        liftIO $ BL.writeFile fp bs
        return $ partOf data

  index <- S.fold_ (\acc (k,v) -> M.insert k v acc) def id $ S.mapM f input

Where the library S is streaming

I tried running it with -M to limit the memory use in case it was just memory that wasn't released to the os but it eventualy crashes because it doesn't have enough memory.

If I remove writeFile it doesn't leak.

If I then evaluate the bytestring manualy and not write it it leaks

If I run the garbage collector after each call it doesn't leak:

  let f data = do
        let bs = getjson data
            fp = getFilepath data
        liftIO $ BL.writeFile fp bs
        return $ partOf data

  index <- S.fold_ (\acc (k,v) -> M.insert k v acc) def id $ S.mapM S.mapM (f >=> (\x -> Mem.performGC >> pure x)) input

I looked at the fragmentation with ghc-debug and there is barely any pinned data after the request terminate.

Expected behavior

I would expect:

  • that the memory use to be the same before running the request and after.
  • that evaluating a bytestring and not using it shouldn't make the program leak.
  • that adding a call the the gc doesn't remove the leak

Environment

  • GHC version used: 9.4.7

Optional:

  • Operating System: Debian 11
  • System Architecture: x86
Edited by Mathieu Bessou
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information