Haskell数据类型的内存占用

我如何找到在Haskell中存储某种数据类型的值所需的实际内存量(主要是使用GHC)? 是否可以在运行时对其进行评估(例如,在GHCi中)还是可以从其组件评估复合数据类型的内存需求?

通常,如果类型ab内存需求是已知的,代数数据类型的内存开销是多少,例如:

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,其他编译器可能使用不同的存储约定)

经验法则: 一个构造函数为一个标题花费一个单词,每个字段花费一个单词 。 例外:没有字段的构造函数(如NothingTrue )不会占用空间,因为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实际上具有IntChar类型的小值缓存,所以在许多情况下,这些根本不占用堆空间。 除非使用Char s> 255,否则String只需要列表单元格的空间。

Int8具有与Int相同的表示形式。 Integer定义如下:

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

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

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

有关GHC评论中堆对象布局的更多详细信息。


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

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

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

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

链接地址: http://www.djcxy.com/p/14069.html

上一篇: Memory footprint of Haskell data types

下一篇: What is private bytes, virtual bytes, working set?