Haskell数据类型的内存占用
我如何找到在Haskell中存储某种数据类型的值所需的实际内存量(主要是使用GHC)? 是否可以在运行时对其进行评估(例如,在GHCi中)还是可以从其组件评估复合数据类型的内存需求?
通常,如果类型a
和b
内存需求是已知的,代数数据类型的内存开销是多少,例如:
data Uno = Uno a
data Due = Due a b
例如,这些值占用内存中有多少个字节?
1 :: Int8
1 :: Integer
2^100 :: Integer
x -> x + 1
(1 :: Int8, 2 :: Int8)
[1] :: [Int8]
Just (1 :: Int8)
Nothing
据我所知,由于垃圾回收延迟,实际内存分配较高。 由于懒惰评估可能会有显着差异(并且thunk大小与值的大小无关)。 问题是,在数据类型的情况下,完全评估时它的值需要多少内存?
我发现GHCi中有一个:set +s
选项来查看内存统计信息,但不清楚如何估计单个值的内存占用量。
(以下适用于GHC,其他编译器可能使用不同的存储约定)
经验法则: 一个构造函数为一个标题花费一个单词,每个字段花费一个单词 。 例外:没有字段的构造函数(如Nothing
或True
)不会占用空间,因为GHC会创建这些构造函数的单个实例并在所有用途中共享它。
一个字在32位机器上是4个字节,而在64位机器上是8个字节。
所以例如
data Uno = Uno a
data Due = Due a b
Uno
需要2个单词, Due
需要3个。
Int
类型定义为
data Int = I# Int#
现在, Int#
需要一个字,所以Int
总共需要2个字。 大多数unboxed类型需要一个单词,例外是Int64#
, Word64#
和Double#
(在32位机器上),它们需要2个.GHC实际上具有Int
和Char
类型的小值缓存,所以在许多情况下,这些根本不占用堆空间。 除非使用Char
s> 255,否则String
只需要列表单元格的空间。
Int8
具有与Int
相同的表示形式。 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的数据类型的内存表示? 以及如何确定Haskell中类型的大小?
链接地址: http://www.djcxy.com/p/14069.html