Skip to content

GHC's internal memory allocator never releases memory back to the OS

allocaBytes does not appear to free the memory after the computation has completed. For example, start ghci and run:

allocaBytes (100*1024*1024) $ \_ -> getLine

ghci's virtual memory usage will jump up by 100MB. When you press enter however, it does not drop back down.

restart ghci and try:

bracket (mallocBytes 100*1024*1024) free $ \_ -> getLine

This time when you press enter, the memory usage will drop back down to its pre mallocBytes usage.

This also happens for compiled programs.

Note: the above test will only alloc virtual memory since nothing is ever read into the malloc'd memory. The following test program will actually force the pages to be mapped. It results in the same broken behaviour with the addition that the resident size of ghci gets stuck high.

module Main where

import Control.Exception 
import Foreign.Marshal.Alloc
import Foreign.Ptr
import Data.Word
import System.IO
import System.Mem

test :: Int -> IO ()
test mb =
    let size = mb * 1024 * 1024 in
        do -- bracket (mallocBytes size) free $ wait size -- this version works
           allocaBytes size $ wait size  -- this version does not free the memory afterwards
           performGC

wait :: Int -> Ptr Word8 -> IO ()
wait size p =    
    bracket (openBinaryFile "/dev/scsi/host0/bus0/target0/lun0/part1" ReadMode) (hClose) (\h -> hGetBuf h p size >> putStrLn "waiting..." >> getLine >> return ()) 

main =
    do test 150
       putStrLn "is it free?"
       getLine
       return ()
Trac metadata
Trac field Value
Version 6.4.1
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler (FFI)
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system Linux
Architecture x86
Edited by Simon Marlow
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information