如果我知道 a 的大小是 x,我想知道 IORef a 类型的变量的内存占用是多少。此外,与 Java 中的常规变量赋值(如 x = 3)相比,应用于整数的函数 writeIORef 的预期性能是什么?
1 回答
在 Haskell 中,an 的IORef a
行为类似于单元素可变数组。的定义如下,IORef
忽略新类型包装:
data IORef a = IORef (MutVar# RealWorld a)
这里,MutVar# RealWorld a
是一个原始的可变引用类型。它是一个指向两个单词的指针,一个标题和一个负载,它本身就是一个指向正常提升的 Haskell 对象的指针。因此,开销MutVar
是两个字(在 64 位系统上为 16 字节)和一个间接。
的开销MutVar#
因此是一个额外的间接和一个额外的标题字。这是不可避免的。相比之下,IORef
构造函数的开销也是一个header word和一个indirection,但是可以通过unpacking来消除IORef
:
data Foo a = Foo !(IORef a) a a
在这里,砰砰声IORef
导致底层证券MutVar
被解包到Foo
. 但是,当我们定义新的数据类型时,这种解包工作,如果我们使用任何现有的参数化类型,如列表,它就不起作用。在[IORef a]
中,我们用两个额外的间接来支付全部成本。
IORef
如果将其用作函数的参数,通常也会被 GHC 优化解包:如果使用优化进行编译,IORef a -> b
通常会被解包为 .MutVar# RealWorld a -> b
但是,当您使用大量-s时,上述所有开销都没有垃圾收集中的开销重要。IORef
为避免这种情况,建议使用单个可变数组而不是多个IORef
-s。