3

如果我知道 a 的大小是 x,我想知道 IORef a 类型的变量的内存占用是多少。此外,与 Java 中的常规变量赋值(如 x = 3)相比,应用于整数的函数 writeIORef 的预期性能是什么?

4

1 回答 1

3

在 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。

于 2020-05-03T22:58:24.077 回答