Haskell数据types的内存占用
我如何find在Haskell中存储一些数据types的值所需的实际内存量(主要是GHC)? 是否有可能在运行时(例如在GHCi中)对其进行评估,还是有可能从组件中估计组合数据types的内存需求?
通常,如果typesa
和b
内存需求是已知的,那么代数数据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,其他编译器可以使用不同的存储约定)
经验法则: 一个构造函数花费一个单词为一个头,每个字段一个单词 。 例外:没有字段的构造函数(如Nothing
或True
)不会占用空间,因为GHC会创build这些构造函数的单个实例并在所有用途中共享它。
一个字在32位机器上是4个字节,而在64位机器上是8个字节。
所以,例如
data Uno = Uno a data Due = Due ab
Uno
需要2个字, Due
需要3个。
Int
types被定义为
data Int = I# Int#
现在, Int#
需要一个字,所以Int
总共需要2个字。 大多数unboxedtypes需要一个单词,例外是Int64#
, Word64#
和Double#
(在一个32位机器上),它需要2个.GHC实际上有一个Int
types和Char
types的小值caching,所以在很多情况下这些根本不占用堆空间。 除非使用Char
> 255,否则String
只需要列表单元格的空间。
Int8
具有与Int
相同的表示forms。 Integer
是这样定义的:
data Integer = S# Int# -- small integers | J# Int# ByteArray# -- large integers
所以一个小Integer
( S#
)需要2个字,但是一个大整数需要一个可变数量的空间,具体取决于它的值。 ByteArray#
需要2个字(头+大小)加上数组本身的空间。
请注意, 用newtype
定义的构造函数是免费的 。 newtype
纯粹是一个编译时间的概念,它不占用空间,在运行时不需要任何指令。
GHC评论中的堆对象布局中的更多细节。
ghc-datasize包提供recursiveSize函数来计算GHC对象的大小。 然而…
垃圾收集在计算大小之前执行,因为垃圾收集器会使堆走难。
…所以经常打电话是不实际的!
另请参阅如何查找GHC的数据types的内存表示? 以及如何确定Haskell中的types的大小? 。