Edited to fix some details re: quads being 8 bytes and explaining the static link field.
I think unsafeSizeOf
is inaccurate and you're misinterpreting its output. Note that it is intended to show the memory usage for the top-level closure only, not the total space usage of the object. What you're seeing, I think, is that q
requires 10 bytes in addition to the tuple p
(while p
requires 10 bytes in addition to the boxed Char
and boxed Int
). Moreover, my tests indicate that the top-level constructors actually require 24 bytes each (on a 64-bit architecture), even though unsafeSizeOf
reports 10 for me, too.
In particular, if I compile the following test program with stack ghc -- -fforce-recomp -ddump-asm -dsuppress-all -O2 ZeroMemory.hs
using GHC 8.0.2:
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeFamilies #-}
module ZeroMemory where
data Uncurry (a :: i -> j -> *) (z :: (i, j)) =
forall x y . z ~ '(x,y) => Uncurry !(a x y)
q :: Uncurry (,) '(Int, Char)
q = Uncurry (0, '\0')
r :: Uncurry (,) '(Int, Char)
r = Uncurry (1, '\1')
then the memory footprint for the top-level q
closure looks like:
q_closure:
.quad Uncurry_static_info
.quad $s$WUncurry_$d~~_closure+1
.quad q1_closure+1
.quad 3
Note that each .quad
here is actually 8 bytes; it's a "quad" of old-style 16-bit "words". I believe the final quad
here, with value 3, is the "static link field" described in the GHC implementation commentary and so doesn't apply to "typical" heap allocation objects.
So, ignoring this final field, the total size of the top-level q
closure is 24 bytes, and it refers to the q1_closure
which represents the contained tuple:
q1_closure:
.quad (,)_static_info
.quad q3_closure+1
.quad q2_closure+1
.quad 3
for another 24 bytes.
The q2
and q3
closures are the boxed Int
and Char
and so take up two quads (16 bytes) each. So, q
takes up a total of 10 quads, or 80 bytes. (I included r
as a sanity check to make sure I wasn't misidentifying any shared info.)
A p
tuple by itself would have a memory footprint equivalent to the q1_closure
, so 7 quads or 56 bytes.