[Haskell-cafe] Daunting heap profile when using (<>)

Tom Ellis tom-lists-haskell-cafe-2013 at jaguarpaw.co.uk
Sat Nov 14 12:23:54 UTC 2015


On Sat, Nov 14, 2015 at 11:10:15AM +0100, martin wrote:
> newtype Logger evt dom log = Lgr {runLogger :: Timed evt -> dom -> (log, Logger evt dom log)}
> 
> runSim :: (Ord evt, Monoid log) => SimBehaviour evt dom log -> SimState evt dom log -> SimState evt dom log
> runSim (!lgr, !hdr, xtp) (!log,!dom,!evq)  =
>         case step of
>             Nothing -> (log, dom, evq) -- end of simulation
>             Just (newEvq, newDom, newHdr, newLgr, newLog) -> runSim (newLgr,newHdr,xtp) (newLog,newDom,newEvq)
>         where
>             -- check for end conditions or run handler
>             step = do
>                 (evt, evts) <- H.view evq -- no more Events -> Nothing
>                 if xtp (evt,dom)  then Nothing
>                 else
>                         let (evq', dom', hdr') = runHandler hdr evt dom
>                             (log',lgr')        = runLogger lgr evt dom'        -- <--
>                         -- append new event and new log entries
>                         in return (evq'<>evts, dom', hdr', lgr', log'<>log)    -- <--
> 
> addLgr (lgr1) (lgr2) = Lgr lgr
>         where
>             lgr tev dom = let (log1', lgr1') = runLogger lgr1  tev dom
>                               (log2', lgr2') = runLogger lgr2  tev dom
>                               (!log') = log2'  <> log1'                       -- x --
> --                          in (log2', addLgr lgr1' lgr2')
>                           in (log', addLgr lgr1' lgr2')
> 
[...]
> Could it be that this is because ! does not fully evaluate its argument, but just to WHNF? Or is there a more obvious
> reason, I just fail to see.

Yes, forcing a list is more-or-less useless, most of the time.  All you're
doing is checking whether the length is zero or non-zero.

> Where to go from here?

The first thing to do would be to check whether

    import Control.DeepSeq

    ...

    !log' = deepseq (log2'  <> log1')

solves the space leak.  If it does then you have found the problem.  That's
not the same thing as finding a solution though!

There are plenty of pre-rolled logging solutions available.  I think I'd
just suggest choosing one of those, rather than implementing your own.

Tom


More information about the Haskell-Cafe mailing list