我如何找到在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,其他编译器可能使用不同的存储约定)
经验法则:构造函数的 header 花费一个词,每个字段花费一个词。异常(exception):没有字段的构造函数(例如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个单词。大部分未装箱的类型都占用一个单词,异常(exception)是Int64#
,Word64#
和Double#
(在32位计算机上),它们占用2。GHC实际上具有小类型Int
和Char
类型的小值的缓存,因此在许多情况下,这些不占用堆空间完全没有空间。除非您使用String
> 255,否则Char
仅需要用于列表单元格的空间。Int8
具有与Int
相同的表示。 Integer
的定义如下:data Integer
= S# Int# -- small integers
| J# Int# ByteArray# -- large integers
因此,一个小的
Integer
(S#
)占用2个字,但是一个大的整数根据其值占用可变的空间量。 ByteArray#
占用2个字(标题+大小)加上数组本身的空间。请注意,用
newtype
定义的构造函数是免费的。 newtype
纯粹是一个编译时想法,它不占用空间,并且在运行时不花费任何指令。在The Layout of Heap Objects in the GHC Commentary中有更多详细信息。
关于haskell - Haskell数据类型的内存占用量,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3254758/