2012-03-10 7 views
13

datos StableName un¿Qué ventajas tiene StableNames sobre reallyUnsafePtrEquality #, y viceversa?

nombres estables tienen la siguiente propiedad: Si SN1 :: StableName y SN2 :: StableName y SN1 == SN2 SN1 y SN2 continuación, fueron creados por las llamadas a makeStableName sobre el mismo objeto.

Lo contrario no es necesariamente cierto: si dos nombres de establo no son iguales, los objetos que nombran pueden ser iguales.

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

reallyUnsafePtrEquality # devuelve si dos objetos en el montón GHC son el mismo objeto. Es realmente inseguro porque el recolector de basura mueve cosas, cierres, etc. Según mi leal saber y entender, puede devolver falsos negativos (dice que dos objetos no son lo mismo, pero lo son), pero no falsos positivos (diciendo que son lo mismo cuando no lo son).

Ambos parecen hacer lo mismo básico: pueden decirle si dos objetos son definitivamente iguales, pero no si definitivamente no lo son.

Las ventajas que puedo ver por StableNames son:

  • Pueden ser hash.
  • Son menos prácticos.
  • Su comportamiento está bien definido y es compatible.
  • No tienen realmente Inseguridad como parte de su nombre.

Las ventajas que puedo ver por reallyUnsafePtrEquality #:

  • se le puede llamar directamente sobre los objetos en cuestión, en lugar de tener que crear StablesNames separadas.
  • No necesita pasar por una función IO para crear los StableNames.
  • No es necesario que mantenga StableNames, por lo que el uso de memoria es menor.
  • El RTS no tiene que hacer la magia que sea para que StableNames funcione, por lo que el rendimiento es presumiblemente mejor.
  • Tiene un nombre muy seguro y un # al final. ¡Duro!

Mis preguntas son:

  • ¿Me he perdido algo?

  • ¿Hay algún caso de uso donde el hecho de que StableNames esté separado de los objetos que nombran es una ventaja?

  • ¿Hay uno más exacto (menos probabilidades de devolver falsos negativos) que el otro?

  • Si no necesita hash, no se preocupa por la portabilidad, y no les molesta usar algo que se llama reallyUnsafe, ¿hay alguna razón para preferir StableNames a reallyUnsafePtrEquality #?

+3

"A mi leal saber y entender, puede devolver falsos negativos (dice que dos objetos no son lo mismo, pero lo son), pero no falsos positivos (diciendo que son iguales cuando no lo son). " Me temo [puede dar falsos positivos] (http://www.haskell.org/pipermail/haskell-cafe/2010-June/079532.html), aunque eso es extremadamente improbable. –

+3

No puedo recordar dónde se discutió esto (podría haber sido IRC), pero las dos razones que recuerdo por las que los falsos positivos son imposibles fueron que GC solo ocurre en la asignación, no durante primops, por lo que no hay forma posible de que interrupte reallyUnsafePtrEquality # para poner un objeto donde estaba el otro; y que los GC del espacio y el espacio no se superponen, por lo que incluso si pudiera, no lo haría. Obviamente, si tanto los falsos negativos como los falsos positivos fueran posibles, sería completamente inútil. – glaebhoerl

+1

Eso suena plausible. Pero, por lo general, Edward K. sabe qué pasa, así que preferiría verificarlo e ignorar alegremente sus advertencias. Sin embargo, el segundo punto descarta los falsos positivos (dos GCs entre ver los dos argumentos para un primop parece demasiado exagerado), incluso si uno no confía completamente en el primero. –

Respuesta

9

Sosteniendo el StableName de un objeto no evitar que sea basura recogida, mientras que sostiene el objeto en sí alrededor (para usar con reallyUnsafePtrEquality# más adelante) lo hace. Claro, puede usar System.Mem.Weak, pero en ese punto, ¿por qué no simplemente usar un StableName? (De hecho, se añadieron punteros débiles con StableName s.)

Ser capaz de hash de ellos es el principal motivador para StableName s, ya que la documentación dice:

No podemos construir una tabla hash usando la dirección del objeto como la clave, ya que los objetos se mueven por el recolector de basura, lo que significa que sería necesario un nuevo hash después de cada recolección de basura.

En general, si StableName s trabajarán para sus propósitos, que haría uso de ellos, incluso si tiene que utilizar unsafePerformIO; si realmente necesita reallyUnsafePtrEquality#, sabrá. El único ejemplo que se puede pensar en que iba a funcionar y reallyUnsafePtrEquality#StableName s no se está acelerando un costoso Eq ejemplo:

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

Probablemente hay otros ejemplos que no he pensado, pero no son comunes .

+1

Buen punto acerca de la recolección de basura y System.Mem.Weak. Aunque supongo que el corolario es: ¿en qué situaciones te gustaría almacenar StableNames aparte de los objetos nombrados? Las tablas hash son una, ¿hay otras? Respecto a su último punto, ¿hay algún motivo específico por el que prefiera StableNames en general? (¿Y existe realmente una situación en la que StableNames no sería adecuado, y realmente sería UltraUnafePtrEquality #?) – glaebhoerl

+1

@illissius: Bueno, la memoración con tablas hash fue el [ejemplo motivador] (http://community.haskell.org/~ simonmar/papers/weak.pdf) para 'StableName's y punteros débiles, por lo que es, con mucho, el ejemplo más destacado. También son útiles para [compartir observable] (http://www.ittc.ku.edu/~andygill/papers/reifyGraph.pdf). – ehird

+0

He actualizado mi publicación con un ejemplo de cuándo 'reallyUnsafePtrEquality #' funcionaría pero 'StableName's no. – ehird

Cuestiones relacionadas