[Haskell-cafe] GHC, odd concurrency space leak

Daniel Fischer daniel.is.fischer at web.de
Sat Apr 17 10:02:45 EDT 2010

Am Samstag 17 April 2010 14:41:28 schrieb Simon Peyton-Jones:
> I have not been following the details of this, I'm afraid, but I notice 
> > forever' m = do _ <- m
> >                 forever' m
> When I define that version of forever, the space leak goes away.
> What was the old version of forever that led to the leak?


forever :: Monad m => m a -> m b
forever m = m >> forever m

However, that isn't the problem. In my tests, both variants of forever 
exhibit the same behaviour, what makes it leak or not is the optimisation 

> If you can boil down the leak to a simple test case, do submit a Trac
> ticket.
> Simon

The code below behaves well if compiled without optimisations (~36K maximum 
When compiled with optimisations (-O1 or -O2, no discernible difference), 
it gets stuck in the infinite loop "always (return ())" [no surprise], but 
it runs in small space (+RTS -M58K for me).
With -O2 -fno-state-hack (or -O1 -fno-state-hack), it leaks memory:
     469,292,260 bytes allocated in the heap
     837,326,332 bytes copied during GC
     233,727,956 bytes maximum residency (9 sample(s))
       3,740,036 bytes maximum slop
             456 MB total memory in use (4 MB lost due to fragmentation) 

module Main (main) where

import Control.Concurrent
always :: Monad m => m a -> m b
always a = a >> always a
always :: Monad m => m a -> m b
always a = do
    _ <- a
    always a

spawner :: IO ()
spawner = always $ do
    forkIO $ always (return ())
    putStrLn "Delaying"
    threadDelay 1000000

main :: IO ()
main = do
    putStrLn "Spawning"
    forkIO spawner
    putStrLn "Delaying main"
    threadDelay 4000000

More information about the Haskell-Cafe mailing list