[Haskell-cafe] ghc-heap-view now with recursive pretty-printing

Joachim Breitner mail at joachim-breitner.de
Fri Dec 21 11:16:02 CET 2012


Hi,

I get the impression that blogs and planet.haskell.org are the best way
to disseminate information about new tools any more. Maybe a part of the
earlier importance has been taken over by GooglePlus, but not all,
leaving both blogs and GooglePlus less useful individually?

Anyways, I’d like to tell you about a feature of ghc-heap-view that I
have blogged about¹, namely the possibility to inspect heap values
recursively in GHCi or in your programs, including thunks, the
references between them and sharing:

Prelude> :script /home/jojo/.cabal/share/ghc-heap-view-0.4.0.0/ghci
Prelude> let x = [1..10]
Prelude> x
[1,2,3,4,5,6,7,8,9,10]
Prelude> :printHeap x
_bh [S# 1,S# 2,S# 3,S# 4,S# 5,S# 6,S# 7,S# 8,S# 9,S# 10]

Note that the tools shows us that the list is a list of S# constructors,
and also that it is still hidden behind a blackhole. After running
System.Mem.performGC, this would disappear.


Prelude> let x = Just (1 + 1)
Prelude> :printHeap x
Just _bco
Prelude> x
Just 2
Prelude> System.Mem.performGC
Prelude> :printHeap x
Just (S# 2)

Here, we see how the calculation was deferred until forced by showing
the value of x. The name _bco stands for a bytecode object as used by
the interpreter. Getting useful information from them is a bit harder
than for compiled thunks, so for more accurate results put the code in a
Haskell source file, compile it and use the GHC.HeapView API to print
the interesting parts.


Prelude> let a = "hi"
Prelude> let partial = (a ++)
Prelude> partial ""
"hi"
Prelude> System.Mem.performGC
Prelude> let x = (a, partial)
Prelude> :printHeap x
let x1 = "hi"
in (x1,_fun x1)

This demonstrates a partial application. The information which function
is called there (++ in this case) is lost at runtime, but we still see
that the second element of the tuple is a partial application of some
value to the first element.


Prelude> let s = "ho"
Prelude> let x = cycle s
Prelude> length (take 100 (show x))
100
Prelude> System.Mem.performGC
Prelude> :printHeap x
let x0 = C# 'h' : C# 'o' : x0
in x0
Prelude> let y = map Data.Char.toUpper x
Prelude> length (take 100 (show y))
100
Prelude> :printHeap y
C# 'H' : C# 'O' : C# 'H' : C# 'O' : C# 'H' : C# 'O' : C# 'H' : C# 'O' : C# 'H' : C# 'O' : _bh (C# 'H' : C# 'O' : C# 'H' : C# 'O' : C# 'H' : C# 'O' : C# 'H' : C# 'O' : ... : ...)

The cyclic, tying-the-knot structure of cycle is very visible. But can
also see how easily it is broken, in this case by mapping a function
over the list.


Prelude> let {x = 'H' : y ; y = 'o' : x }
Prelude> length (show (take 10 x, take 10 y)) `seq` return ()
Prelude> System.Mem.performGC
Prelude> :printHeap (x,y)
let x1 = C# 'H' : x3
    x3 = C# 'o' : x1
in (x1,x3)

If you want to look at multiple variables at once, just pass a tuple to
printHeap


I hope you’ll find it useful, and I am happy to hear about other
features that you might be interested in.

Also, if you don’t know about it, a graphical and interactive variant of
this is available as ghc-vis².

Greetings,
Joachim

¹ http://www.joachim-breitner.de/blog/archives/580-GHCi-integration-for-GHC.HeapView.html
² http://felsin9.de/nnis/ghc-vis/
-- 
Joachim "nomeata" Breitner
  mail at joachim-breitner.de  |  nomeata at debian.org  |  GPG: 0x4743206C
  xmpp: nomeata at joachim-breitner.de | http://www.joachim-breitner.de/

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: This is a digitally signed message part
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20121221/299c35c9/attachment.pgp>


More information about the Haskell-Cafe mailing list