StableNames对真正的不安全性质量有什么优势,反之亦然? [英] What advantages do StableNames have over reallyUnsafePtrEquality#, and vice versa?

查看:77
本文介绍了StableNames对真正的不安全性质量有什么优势,反之亦然?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

数据 StableName a
$ b


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



反过来不一定是真的:如果两个稳定名称不相等,那么它们的名称可能仍然相同。

blockquote>

reallyUnsafePtrEquality# :: a - > a - > Int#



reallyUnsafePtrEquality#返回GHC堆上的两个对象是否是同一个对象。这是非常不安全的,因为垃圾收集器会移动东西,关闭等等。据我所知,它可以返回错误的否定结果(它表示两个对象不一样,但它们是),但不是误报(他们说他们两个似乎都做了同样的基本事情:他们可以告诉你两个物体是否完全相同,但是,而不是他们是否肯定不是。



StableNames的优点是:
$ b $ ul

  • 它们可以被散列。

  • 它们不易携带。

  • 它们的行为已被良好定义和支持。 b $ b
  • 他们没有真正的安全作为他们名字的一部分。



  • 我可以看到真正的优势不可能的优势#:


    • 它可以直接在有问题的对象上调用,而不必创建单独的StablesNames。

    • <李>你不必经历一个IO功能创建StableNames。
    • 您不必保留StableNames,因此内存使用率较低。

    • RTS没有尽可能让StableNames起作用,所以性能可能更好。

    • 它的名字真的很不安全,最后还有一个#。 Hardcore!



    我的问题是:
    $ b $ ul

  • 我错过了什么吗?

  • 是否有任何用例说明StableNames与它们命名的对象是分开的这一事实?


  • 其中一个更精确(不太可能返回假阴性)比另一个更精确。

  • 如果你不需要散列,不关心可移植性,也不会为使用真正的不安全而烦恼,是否有任何理由更喜欢StableNames而不是真正的不安全性?



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



    能够散列它们是主要动力对于 StableName s,如文档所述:


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


    一般来说,如果 StableName s可以用于您的目的,即使您需要使用 unsafePerformIO ;如果你真的需要 reallyUnsafePtrEquality#,你就会知道。我能想到的唯一例子是 reallyUnsafePtrEquality#会起作用, StableName s不会加速昂贵的 Eq instance:

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

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

    data StableName a

    Stable names have the following property: If sn1 :: StableName and sn2 :: StableName and sn1 == sn2 then sn1 and sn2 were created by calls to makeStableName on the same object.

    The reverse is not necessarily true: if two stable names are not equal, then the objects they name may still be equal.

    reallyUnsafePtrEquality# :: a -> a -> Int#

    reallyUnsafePtrEquality# returns whether two objects on the GHC heap are the same object. It's really unsafe because the garbage collector moves things around, closures, etc. To the best of my knowledge, it can return false negatives (it says two objects aren't the same, but they are), but not false positives (saying they're the same when they aren't).

    Both of them seem to do the same basic thing: they can tell you whether two objects are definitely the same, but not whether they're definitely not.

    The advantages I can see for StableNames are:

    • They can be hashed.
    • They are less nonportable.
    • Their behaviour is well-defined and supported.
    • They don't have reallyUnsafe as part of their name.

    The advantages I can see for reallyUnsafePtrEquality#:

    • It can be called directly on the objects in question, instead of having to create separate StablesNames.
    • You don't have to go through an IO function to create the StableNames.
    • You don't have to keep StableNames around, so memory usage is lower.
    • The RTS doesn't have to do whatever magic it does to make the StableNames work, so performance is presumably better.
    • It has reallyUnsafe in the name and a # at the end. Hardcore!

    My questions are:

    • Did I miss anything?

    • Is there any use case where the fact that StableNames are separate from the objects they name is an advantage?

    • Is either one more accurate (less likely to return false negatives) than the other?

    • If you don't need hashing, don't care about portability, and aren't bothered by using something called reallyUnsafe, is there any reason to prefer StableNames over reallyUnsafePtrEquality#?

    解决方案

    Holding the StableName of an object doesn't prevent it from being garbage collected, whereas holding the object itself around (to use with reallyUnsafePtrEquality# later) does. Sure, you can use System.Mem.Weak, but at that point, why not just use a StableName? (In fact, weak pointers were added with StableNames.)

    Being able to hash them is the main motivator for StableNames, as the documentation says:

    We can't build a hash table using the address of the object as the key, because objects get moved around by the garbage collector, meaning a re-hash would be necessary after every garbage collection.

    In general, if StableNames will work for your purposes, I'd use them, even if you need to use unsafePerformIO; if you really need reallyUnsafePtrEquality#, you'll know. The only example I can think of where reallyUnsafePtrEquality# would work and StableNames wouldn't is speeding up an expensive Eq instance:

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

    There's probably other examples I just haven't thought of, but they're not common.

    这篇关于StableNames对真正的不安全性质量有什么优势,反之亦然?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆