StableNames比reallyUnsafePtrEquality#有什么优势,反之亦然?

时间:2012-03-10 19:30:34

标签: haskell ghc

数据StableName a

  

稳定名称具有以下属性:    如果sn1 :: StableName和sn2 :: StableName和sn1 == sn2,那么sn1和sn2是通过对同一对象调用makeStableName创建的。

     

反过来不一定如此:如果两个稳定名称不相等,那么它们命名的对象可能仍然相等。

reallyUnsafePtrEquality# :: a - > a - > INT#

reallyUnsafePtrEquality#返回GHC堆上的两个对象是否是同一个对象。这真的是不安全的,因为垃圾收集器移动东西,闭包等。据我所知,它可以返回假阴性(它说两个对象不一样,但它们是),但不是误报(说它们当它们不相同时,它们会一样。

他们两个似乎都做了同样的基本事情:他们可以告诉你两个对象是否绝对相同,但不是它们是否绝对不是。

我可以看到StableNames的优点是:

  • 他们可以被散列。
  • 他们不太便宜。
  • 他们的行为定义明确并受到支持。
  • 他们没有真正的不安全作为他们名字的一部分。

我可以在reallyUnsafePtrEquality#:

中看到的优势
  • 可以直接在相关对象上调用它,而不必创建单独的StablesNames。
  • 您无需通过IO功能来创建StableNames。
  • 您不必保留StableNames,因此内存使用率会降低。
  • RTS不需要做任何使StableNames工作的魔法,所以性能可能更好。
  • 名称中有真正的安全,最后是#。铁杆!

我的问题是:

  • 我错过了什么吗?

  • 是否存在StableNames与其所命名的对象分开的事实是否有用?

  • 是否比另一个更准确(不太可能返回假阴性)?

  • 如果你不需要散列,不关心可移植性,并且不会被使用名为reallyUnsafe的东西打扰,是否有理由更喜欢StableNames而不是reallyUnsafePtrEquality#?

1 个答案:

答案 0 :(得分:9)

持有对象的StableName并不能防止它被垃圾收集,而持有对象本身(以后与reallyUnsafePtrEquality#一起使用)可以。当然,您可以使用System.Mem.Weak,但此时,为什么不使用StableName? (实际上,弱指针添加了StableName s。)

能够散列它们是StableName的主要动力,正如文档所说:

  

我们不能使用对象的地址作为键来构建哈希表,因为对象会被垃圾回收器移动,这意味着每次垃圾回收后都需要重新哈希。

一般情况下,如果StableName s适用于您的目的,即使您需要使用unsafePerformIO,我也会使用它们。如果你真的需要reallyUnsafePtrEquality#,你就会知道。我能想到reallyUnsafePtrEquality#工作的唯一示例和StableName s不会加速昂贵的Eq实例:

x == y =
    x `seq` y `seq`
    case reallyUnsafePtrEquality# x y of
        1# -> True
        _  -> slowEq x y

可能还有其他一些我想不到的例子,但它们并不常见。