Ticket #698 (closed bug: fixed)
GHC's internal memory allocator never releases memory back to the OS
|Reported by:||guest||Owned by:||igloo|
|Keywords:||Cc:||Bulat.Ziganshin@…, barsoap@…, gwern0@…, asklingenberg@…, ndmitchell@…, gale@…, pho@…, rturk@…|
|Type of failure:||None/Unknown||Difficulty:||Moderate (less than a day)|
|Test Case:||Blocked By:|
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 ()