如果我知道a的大小是x,我想知道IORef a类型的变量的内存占用量是多少。此外,在Java中,应用于integer compare的函数writeIORef的预期性能是什么?
在Haskell中,IORef a
的行为类似于单个元素的可变数组。IORef
的定义如下,不考虑换行:
data IORef a = IORef (MutVar# RealWorld a)
这里,MutVar# RealWorld a
是一个基元可变引用类型。它是一个指向两个单词的指针,一个标头和一个有效负载,有效负载本身就是一个指向正常提升的Haskell对象的指针。因此,MutVar
的开销是两个字(在64位系统上为16字节(和一个间接。
MutVar#
的开销因此是一个额外的间接和一个额外头字。这是不可避免的。相反,IORef
构造函数的开销也是一个头字和一个间接,但可以通过拆包IORef
:来消除
data Foo a = Foo !(IORef a) a a
这里,IORef
上的bang导致底层MutVar
被解包到Foo
中。但是,尽管每当我们定义新的数据类型时,这种拆包都可以工作,但如果我们使用任何现有的参数化类型(如列表(,它就不起作用。在[IORef a]
中,我们用两个额外的间接词支付全部费用。
如果IORef
被用作函数的参数,它通常也会被GHC优化解包:如果使用优化编译,IORef a -> b
通常会被解包到MutVar# RealWorld a -> b
。
但是,当使用大量IORef
-s时,上述所有开销都不如垃圾收集中的开销重要。为了避免这种情况,建议使用单个可变数组,而不是多个IORef
-s。