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).
How about adding a bang patterns to the formal parameter a? That way we don’t need to use $! all the time.
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?
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.
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.
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).