Haskell数据types的内存占用

我如何find在Haskell中存储一些数据types的值所需的实际内存量(主要是GHC)? 是否有可能在运行时(例如在GHCi中)对其进行评估,还是有可能从组件中估计组合数据types的内存需求?

通常,如果typesab内存需求是已知的,那么代数数据types的内存开销是多less,例如:

 data Uno = Uno a data Due = Due ab 

例如,这些值占用内存中有多less个字节?

 1 :: Int8 1 :: Integer 2^100 :: Integer \x -> x + 1 (1 :: Int8, 2 :: Int8) [1] :: [Int8] Just (1 :: Int8) Nothing 

我知道实际的内存分配比较高,因为垃圾回收的延迟。 由于懒惰评估可能会有很大的不同(并且thunk的大小与值的大小无关)。 问题是,在给定数据types的情况下,在完全评估时它的值需要多less内存?

我发现GHCi中有一个:set +s选项来查看内存统计信息,但不清楚如何估计单个值的内存占用情况。

(以下适用于GHC,其他编译器可以使用不同的存储约定)

经验法则: 一个构造函数花费一个单词为一个头,每个字段一个单词 。 例外:没有字段的构造函数(如NothingTrue )不会占用空间,因为GHC会创build这些构造函数的单个实例并在所有用途中共享它。

一个字在32位机器上是4个字节,而在64位机器上是8个字节。

所以,例如

 data Uno = Uno a data Due = Due ab 

Uno需要2个字, Due需要3个。

Inttypes被定义为

 data Int = I# Int# 

现在, Int#需要一个字,所以Int总共需要2个字。 大多数unboxedtypes需要一个单词,例外是Int64#Word64#Double# (在一个32位机器上),它需要2个.GHC实际上有一个Inttypes和Chartypes的小值caching,所以在很多情况下这些根本不占用堆空间。 除非使用Char > 255,否则String只需要列表单元格的空间。

Int8具有与Int相同的表示forms。 Integer是这样定义的:

 data Integer = S# Int# -- small integers | J# Int# ByteArray# -- large integers 

所以一个小IntegerS# )需要2个字,但是一个大整数需要一个可变数量的空间,具体取决于它的值。 ByteArray#需要2个字(头+大小)加上数组本身的空间。

请注意, newtype定义的构造函数是免费的newtype纯粹是一个编译时间的概念,它不占用空间,在运行时不需要任何指令。

GHC评论中的堆对象布局中的更多细节。

ghc-datasize包提供recursiveSize函数来计算GHC对象的大小。 然而…

垃圾收集在计算大小之前执行,因为垃圾收集器会使堆走难。

…所以经常打电话是不实际的!

另请参阅如何查找GHC的数据types的内存表示? 以及如何确定Haskell中的types的大小? 。