Ever wondered how big a closure is?

Somebody asked me yesterday how to find out how big the runtime representation of a type is. I hacked this up using the internal unpackClosure# primitive:

{-# LANGUAGE MagicHash,UnboxedTuples #-}
module Size where

import GHC.Exts
import Foreign

unsafeSizeof :: a -> Int
unsafeSizeof a = 
  case unpackClosure# a of 
    (# x, ptrs, nptrs #) -> 
      sizeOf (undefined::Int) + -- one word for the header
        I# (sizeofByteArray# (unsafeCoerce# ptrs) 
             +# sizeofByteArray# nptrs)

Try it in GHCi:

Prelude> :!ghc -c Size.hs
Prelude> :l Size
Ok, modules loaded: Size.
Prelude Size> unsafeSizeof 3.3
16
Prelude Size> unsafeSizeof "a"
24
Prelude Size> unsafeSizeof (1,2,3,4)
40
Prelude Size> unsafeSizeof True
8
Prelude Size> unsafeSizeof $! Data.Complex.(:+) 2 3
24
Prelude Size> unsafeSizeof $! 3
16
Prelude Size> unsafeSizeof $! (3::Integer)
16
Prelude Size> unsafeSizeof $! (3::Int)
16
Prelude Size> unsafeSizeof $! (2^64::Integer)
24

I’m on a 64-bit machine, obviously. It doesn’t always do the right thing, but for ordinary algebraic types it should work most of the time. Remember to use $!, as the size returned for an unevaluated thunk is always just one word (unpackClosure# doesn’t work for thunks).

This entry was posted in Uncategorized. Bookmark the permalink.

5 Responses to Ever wondered how big a closure is?

  1. svenningsson says:

    How about adding a bang patterns to the formal parameter a? That way we don’t need to use $! all the time.

  2. sweirich says:

    Neat! We we’re just talking yesterday about calculating the sizes of values in memory in GHC. Is there any way to make this recursive, so that it can calculate the entire size of a tree in memory? Is there another way to determine that?

  3. simonmar says:

    sweirich: recursive is difficult, you’d have to worry about cycles, and trying to catch the cycles in Haskell would be hard because the GC tends to change the address of objects.

    I think the only (sensible) way to do that would be in the RTS.

  4. A little pointer for those who come across this blog post: A student of mine created ghc-datasize to calculate the size of individual thunks or whole trees: http://felsin9.de/nnis/ghc-datasize/. It does not yet work for cyclic structures, but that should be possible, as the related project ghc-vis (http://felsin9.de/nnis/ghc-vis) supports that.

  5. Ignore “It does not yet work for cyclic structures, but that should be possible, as the related project ghc-vis (http://felsin9.de/nnis/ghc-vis) supports that.”, ghc-datasize does support correct counting of cyclic data structures (function recursiveSize).

Leave a comment