[Haskell-cafe] help diagnosing space leak with IORef/STRef, just incrementing a million times.
Thomas Hartman
thomashartman1 at gmail.com
Mon Jan 7 06:12:14 CET 2013
I have a space leak in a function that increments a number inside
IORef or STRef (either lazy or strict).
Is this the kind of problem that can be diagnosed and fixed using the
approach described in RWH, with space profiling? Otherwise what's the
right approach to diagnose and fix?
I wrote a non-list-using, and tail call-using, iterateMonadic funcation
that does the same thing as replicateM, in case the problem was due to
iterateM using a list structure, but iterateMonadic and replicateM had
same memory leak.
I can run this problem with +RTS -K100M -RTS but this aditional memory
shouldn't be needed.
{-# LANGUAGE RankNTypes, BangPatterns #-}
import Data.List
import Control.Monad.State.Strict
import Data.Array.MArray
import Data.Array.IO
import Data.Array.ST
import Control.Monad.ST
import Control.Applicative
import Data.IORef
import Data.STRef.Strict
import Data.STRef
import GHC.ST
import Control.Applicative ((<$>))
main = do
-- putStrLn "ioIters, iterateMonadic: "
-- print =<< ioIters iters iterateMonadic
-- putStrLn "ioIters, replicateM_: "
-- print =<< ioIters iters replicateM_
-- putStrLn "lazySTIters, iterateMonadic: "
-- print $ lazySTIters iters iterateMonadic
-- putStrLn "lazySTIters, replicateM_: "
-- print $ lazySTIters iters replicateM_
putStrLn "strictSTIters, iterateMonadic: "
print $ strictSTIters iters iterateMonadic
-- putStrLn "strictSTIters, replicateM_: "
-- print $ strictSTIters iters replicateM_
type Iter = (Monad m) => Int -> m () -> m ()
iterateMonadic :: (Monad m) => Int -> m a -> m a
iterateMonadic n mx = do
let loop 0 acc = acc
loop n acc = loop (n-1) (acc >> mx )
loop n mx
iters = 10^7
ioIters :: Int -> Iter -> IO Int
ioIters numIters iteratorM = do
tmp <- newIORef 0
iteratorM numIters ( modifyIORef tmp (+1) )
readIORef tmp
lazySTIters :: Int -> Iter -> Int
lazySTIters numIters iteratorM = runST $ do
tmp <- Data.STRef.newSTRef 0
iteratorM numIters ( Data.STRef.modifySTRef tmp (+1) )
Data.STRef.readSTRef tmp
strictSTIters :: Int -> Iter -> Int
strictSTIters numIters iteratorM = runST $ do
tmp <- Data.STRef.Strict.newSTRef 0
iteratorM numIters ( Data.STRef.Strict.modifySTRef tmp incr' )
Data.STRef.Strict.readSTRef tmp
incr' (!x) = x + 1
More information about the Haskell-Cafe
mailing list