代码之家  ›  专栏  ›  技术社区  ›  sastanin

Haskell数据类型的内存占用

  •  118
  • sastanin  · 技术社区  · 14 年前

    如何在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大小与值的大小无关),它可能会有很大的不同。问题是,给定一个数据类型,当完全求值时,它的值需要多少内存?

    我发现有一个 :set +s 选项查看内存统计信息,但不清楚如何估计单个值的内存占用。

    2 回复  |  直到 7 年前
        1
  •  158
  •   Simon Marlow    14 年前

    经验法则: . 例外:没有字段的构造函数(如 Nothing True )不占用空间,因为GHC创建这些构造函数的单个实例并在所有用户之间共享它。

    字在32位机器上是4字节,在64位机器上是8字节。

    data Uno = Uno a
    data Due = Due a b
    

    Uno 两个字,一个 Due 需要3分钟。

    Int

    data Int = I# Int#
    

    现在, Int# 只需要一个词,所以 总共需要2个。大多数未装箱的类型只接受一个单词,例外情况是 Int64# Word64# ,和 Double# (在32位机器上)需要2。GHC实际上有一个类型为 Char ,因此在许多情况下,这些根本不占用堆空间。A String 除非使用 烧焦 s>255

    Int8 具有与相同的表示形式 内景 . Integer

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

    这么小 整数 ( S# )需要2个字,但大整数需要可变的空间量,这取决于它的值。A ByteArray# 取2个字(头+大小)加上数组本身的空间。

    用定义的构造函数 newtype 新类型 完全是编译时的思想,在运行时不占用任何空间,也不消耗任何指令。

    更多详细信息请参见 The Layout of Heap Objects in the GHC Commentary

        2
  •  5
  •   Community holdenweb    7 年前

    ghc datasize包提供 recursiveSize

    因为垃圾收集器会使堆行走变得困难。

    …所以经常打电话是不现实的!

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