编辑修复了一些细节:四边形是 8 个字节并解释了静态链接字段。
我认为unsafeSizeOf 不准确并且您误解了它的输出。请注意,它仅显示顶级闭包的内存使用情况,而不是对象的总空间使用情况。我认为您所看到的是 q 需要 10 个字节在 addition 到元组 p (而 p 需要 10 个字节在 addition 到盒装的Char 和盒装的Int)。此外,我的测试表明顶级构造函数实际上每个都需要 24 个字节(在 64 位架构上),尽管 unsafeSizeOf 也为我报告了 10 个字节。
特别是,如果我使用 GHC 8.0.2 使用 stack ghc -- -fforce-recomp -ddump-asm -dsuppress-all -O2 ZeroMemory.hs 编译以下测试程序:
{-# 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')
那么顶级 q 闭包的内存占用如下所示:
q_closure:
.quad Uncurry_static_info
.quad $s$WUncurry_$d~~_closure+1
.quad q1_closure+1
.quad 3
注意这里每个.quad其实是8个字节;它是旧式 16 位“字”的“四边形”。我相信这里的最终quad,值为3,是the GHC implementation commentary 中描述的“静态链接字段”,因此不适用于“典型”堆分配对象。
所以,忽略这个final字段,顶层q闭包的总大小为24字节,它指的是代表包含元组的q1_closure:
q1_closure:
.quad (,)_static_info
.quad q3_closure+1
.quad q2_closure+1
.quad 3
另外 24 个字节。
q2 和 q3 闭包是装箱的 Int 和 Char,因此每个都占用两个四边形(16 字节)。因此,q 总共占用 10 个四边形,即 80 个字节。 (我将r 包括在内,以确保我没有误认任何共享信息。)
p 元组本身的内存占用量与q1_closure 相同,因此是 7 个四边形或 56 个字节。