[GHC] #12566: Memory leak
GHC
ghc-devs at haskell.org
Sat Sep 3 10:56:51 UTC 2016
#12566: Memory leak
-------------------------------------+-------------------------------------
Reporter: igloo | Owner:
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 8.0.1
Keywords: | Operating System: Unknown/Multiple
Architecture: | Type of failure: None/Unknown
Unknown/Multiple |
Test Case: | Blocked By:
Blocking: | Related Tickets:
Differential Rev(s): | Wiki Page:
-------------------------------------+-------------------------------------
With the attached write.hs (which generates a file called "data") and
read.hs (which consumes that file), if I run
{{{
ghc -Wall -Werror -O write.hs -o write
ghc -Wall -Werror -O -prof -auto-all read.hs -o read1
ghc -Wall -Werror -O -prof -auto-all read.hs -o read2 -DLEAK
./write
./read1 +RTS -h
./read2 +RTS -h
}}}
then read2's heap profile shows that it is retaining a lot of extra data.
Perhaps I am missing something, but I can't see why this needs to be
retained. I would expect the two heap profiles to look the same.
Sources and heap profiles (using GHC 8.0.1) attached. I've copied the
sources below for convenience:
write.hs:
{{{#!hs
module Main (main) where
import qualified Data.ByteString.Lazy.Char8 as L
main :: IO ()
main = L.writeFile "data" $ L.concat $ map mkByteString [1..100000]
mkByteString :: Int -> L.ByteString
mkByteString i = L.concat (L.pack ("#" ++ show i ++ "\n")
: replicate 100 (L.pack "Something else\n"))
}}}
read.hs:
{{{#!hs
{-# LANGUAGE BangPatterns, CPP #-}
module Main (main) where
import Data.List
import Data.Set (Set)
import qualified Data.Set as Set
import qualified Data.ByteString.Char8 as S
import qualified Data.ByteString.Lazy.Char8 as L
main :: IO ()
main = do bs <- L.readFile "data"
let stats = getMaybes bs
s = mkSet stats
print $ Set.size s
mkSet :: [Maybe S.ByteString] -> Set S.ByteString
mkSet ms = foldl' f Set.empty ms
where f s (Just l) = Set.insert l s
f s _ = s
getMaybes :: L.ByteString -> [Maybe S.ByteString]
getMaybes bs = if L.null bs then []
else case getMaybe bs of
(stat, bs') ->
stat : getMaybes bs'
getMaybe :: L.ByteString -> (Maybe S.ByteString, L.ByteString)
getMaybe bs = case L.uncons bs of
Just ('#', bs') ->
case L.break ('\n' ==) bs' of
(l, bs'') ->
let !l' = copy l
in (Just l', bs'')
_ ->
case L.break ('\n' ==) bs of
(_x, bs') ->
#ifdef LEAK
copy _x `seq`
#endif
(Nothing, L.tail bs')
copy :: L.ByteString -> S.ByteString
copy bs = S.copy $ L.toStrict bs
}}}
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/12566>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list