ChatGPT解决这个技术问题 Extra ChatGPT

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 选项可以查看内存统计信息,但不清楚如何估计单个值的内存占用量。


S
Simon Marlow

(以下适用于 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# 占用 1 个单词,因此 Int 总共占用 2 个单词。大多数未装箱类型占用一个字,Int64#Word64#Double#(在 32 位机器上)例外,它们占用 2。GHC 实际上有一个 Int 和 {7 类型的小值的缓存},所以在很多情况下,它们根本不占用堆空间。 String 只需要列表单元格的空间,除非您使用 Chars > 255.

Int8Int 具有相同的表示。 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 中有更多详细信息。


谢谢你,西蒙。这正是我想知道的。
标题不是两个字吗?一个用于标记,一个用于在 GC 或评估期间使用的转发指针?那么这不会在你的总数中增加一个词吗?
@Edward:Thunk 被间接覆盖(后来被 GC 删除),但它们只有 2 个字,并且每个堆对象的大小都保证至少有两个 2 个字。如果没有打开任何分析或调试功能,标题真的只有一个字。也就是说,在 GHC 中,其他实现可能会做不同的事情。
nominolo: 是的,但是来自 Closure.h: /* thunk 有一个填充词来获取更新的值。这样更新不会覆盖有效负载,因此我们可以避免在进入和更新期间需要锁定 thunk。注意:这不适用于没有负载的 THUNK_STATIC。注意:我们以各种方式保留此填充词,而不仅仅是 SMP,这样我们就不必为 SMP 重新编译所有库。 */ 有效载荷在间接期间不会被覆盖。间接写入在 Header 中的单独位置。
是的,但请注意,这仅适用于 thunk。它不适用于构造函数。无论如何,估计一个 thunk 的大小有点困难——你必须计算自由变量。
C
Community

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

在计算大小之前执行垃圾收集,因为垃圾收集器会使堆遍历变得困难。

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

另请参阅 How to find out GHC's memory representations of data types?How can I determine size of a type in Haskell?


关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅