heap profiling
Evan Laforge
qdunkan at gmail.com
Wed Jun 23 02:05:02 EDT 2010
> Right, I wouldn't use DList for this. Here's an alternative I use:
>
> data AList a = ANil | ASing a | Append (AList a) (AList a)
>
> lenA :: AList a -> Int
> lenA ANil = 0
> lenA (ASing _) = 1
> lenA (Append l r) = lenA l + lenA r
>
> appendA ANil r = r
> appendA l ANil = l
> appendA l r = Append l r
>
> Note how appendA is strict(ish) and eliminates ANils, so in a writer monad
> it shouldn't build up a space leak. I'm sure you can write toList (don't
> use (++) though).
I hope you're not overestimating me :) I thrashed around for a good
long time trying to get (++) to associate to the right, and then
stumbled across OrdList in ghc, which is apparently just this data
structure, with the addition of 'Many [a]'.
> I'd put the bang on ws:
>
> m>>= k = WriterT $ do
> (a, w) <- runWriterT m
> (b, w') <- runWriterT (k a)
> let !ws = w `mappend` w'
> return (b, ws)
>
> The problem with this monad is that >>= isn't tail-recursive, so it will
> cause stack overflows on recursive monadic functions. I suspect that a
> better alternative to the strict writer monad is the strict state monad in
> most cases, because its bind is tail-recursive.
Bang on 'ws' was my first instinct too, but it appeared to have no
effect. I tried to work out a manual reduction for >>= to figure out
exactly what is being forced when, but I got a headache and decided to
do something more relaxing, like watch Primer.
Yes, I suppose Writer's >>= isn't tail recursive... which seems like a
disaster for >>=, since they are usually composed into very long
chains. I know non-tail recursiveness isn't necessarily a disaster in
haskell because of laziness, but it seems like you need just one
strict monad in the stack, like ErrorT or IO and you are no longer
lazy.
I implemented LoggerT as a strict state monad, and I think it got
better, but there's still a lot of garbage coming from somewhere.
AppendList actually seems slower in the face of repeated appends than
(:) followed by reverse, as I mentioned in the other email. Or it
could be I'm not measuring things right...
>> I also have a situation where -hb shows about 4mb of drag at the most,
>> but when I run with '-hc -hbdrag', I only see 10k peaks. Shouldn't
>> filtering the graph by drag add up to as much drag as when the graph
>> isn't filtered?
>
> That sounds suspicious. If you can make a self-contained example that
> demonstrates it and create a ticket, that would be a great help.
Ok, I'll try to reduce this to a manageable size. It's the same code
that produces the deadlock while profiling, so perhaps that's related.
thanks again for the advice!
More information about the Glasgow-haskell-users
mailing list