2012-03-10 17 views
13

dati StableName unQuali sono i vantaggi di StableNames rispetto a reallyUnsafePtrEquality # e viceversa?

nomi stabili hanno la seguente proprietà: Se sn1 :: StableName e SN2 :: StableName e sn1 == SN2 poi sn1 e SN2 sono stati creati da chiamate verso makeStableName sullo stesso oggetto.

L'inverso non è necessariamente vero: se due nomi stabili non sono uguali, gli oggetti che chiamano possono essere uguali.

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

reallyUnsafePtrEquality # restituisce se due oggetti sul mucchio GHC sono lo stesso oggetto. È davvero pericoloso perché il garbage collector sposta le cose intorno, chiusure, ecc. Per quanto ne so, può restituire falsi negativi (dice che due oggetti non sono gli stessi, ma lo sono), ma non i falsi positivi (dicendo che Sono uguali quando non lo sono).

Entrambi sembrano fare la stessa cosa di base: possono dirti se due oggetti sono sicuramente gli stessi, ma non se lo sono sicuramente.

I vantaggi che posso vedere per StableNames sono:

  • Possono essere hash.
  • Sono meno non portabili.
  • Il loro comportamento è ben definito e supportato.
  • Non hanno davvero sicuro come parte del loro nome.

I vantaggi che posso vedere per reallyUnsafePtrEquality #:

  • può essere chiamato direttamente sugli oggetti in questione, invece di dover creare StablesNames separati.
  • Non è necessario passare attraverso una funzione IO per creare nomi stabili.
  • Non è necessario mantenere StableNames in giro, quindi l'utilizzo della memoria è inferiore.
  • L'RTS non deve fare alcuna magia per far funzionare gli StableNames, quindi le prestazioni sono presumibilmente migliori.
  • Ha davvero un sicuro nel nome e un # alla fine. Hardcore!

Le mie domande sono:

  • Mi sono perso qualcosa?

  • C'è qualche caso d'uso in cui il fatto che StableNames siano separati dagli oggetti che nominano è un vantaggio?

  • È uno più preciso (meno probabile che restituisca i falsi negativi) rispetto all'altro?

  • Se non hai bisogno dell'hashing, non ti preoccupare della portabilità e non ti preoccupare di usare qualcosa chiamato veramente Unsafe, c'è qualche motivo per preferire StableNames su reallyUnsafePtrEquality #?

+3

"Per quanto ne so, può restituire falsi negativi (si dice che due oggetti non sono gli stessi, ma lo sono), ma non i falsi positivi (dicendo che sono gli stessi quando non lo sono). " Ho paura [può dare falsi positivi] (http://www.haskell.org/pipermail/haskell-cafe/2010-June/079532.html), anche se questo è estremamente improbabile. –

+3

Non riesco a ricordare dove è stato discusso (potrebbe essere stato IRC), ma i due motivi per cui ricordo perché i falsi positivi sono impossibili erano che il GC si verifica solo a allocazione, non durante i primops, quindi non c'è modo possibile interrompi veramenteUnsafePtrEquality # per mettere un oggetto dove era l'altro; e che i GC dallo spazio-spazio allo spazio non si sovrappongono, quindi anche se potesse, non lo farebbe. Ovviamente se fossero possibili sia i falsi negativi che i falsi positivi sarebbe completamente inutile. – glaebhoerl

+1

Sembra plausibile. Ma di solito Edward K. sa cosa succede, quindi preferirei ricontrollare che ignorare allegramente i suoi avvertimenti. Tuttavia, il secondo punto esclude quasi tutti i falsi positivi (due GC tra l'osservazione dei due argomenti per un primop sembra un po 'troppo inverosimile), anche se uno non si fida completamente del primo. –

risposta

9

Tenendo la StableName di un oggetto non impedisce che venga garbage collection, che tiene l'oggetto stesso muoversi (da usare con reallyUnsafePtrEquality# seguito) fa. Certo, puoi usare System.Mem.Weak, ma a quel punto, perché non usare solo un StableName? (In realtà, sono stati aggiunti i puntatori deboli con StableName s.)

Essere in grado di hash loro è la motivazione principale per StableName s, come la documentazione dice:

Non possiamo costruire una tabella hash utilizzando l'indirizzo dell'oggetto come chiave, perché gli oggetti vengono spostati dal garbage collector, il che significa che un re-hash sarebbe necessario dopo ogni garbage collection.

In generale, se StableName s lavorerà per i vostri scopi, mi piacerebbe li uso, anche se è necessario utilizzare unsafePerformIO; se hai davvero bisogno di reallyUnsafePtrEquality#, lo saprai. L'unico esempio mi viene in mente dove avrebbe funzionato reallyUnsafePtrEquality# e StableName s non sta accelerando un costoso Eq esempio:

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

C'è probabilmente altri esempi io non ho pensato, ma non sono comuni .

+1

Un buon punto sulla raccolta dei rifiuti e su System.Mem.Weak. Però immagino che il corollario sia: in quali situazioni vorresti memorizzare StableNames oltre agli oggetti nominati? I tavoli hash sono uno, ci sono altri? Per quanto riguarda il tuo ultimo punto, c'è qualche motivo specifico che preferiresti StableNames in generale? (E in realtà esiste una situazione in cui StableNames non sarebbe adatto, e davveroUnsafePtrEquality # sarebbe?) – glaebhoerl

+1

@illisio: Beh, la memo con le tabelle hash era [l'esempio motivante] (http://community.haskell.org/~ simonmar/papers/weak.pdf) per 'StableName' e puntatori deboli, quindi questo è di gran lunga l'esempio più importante. Sono anche utili per [condivisione osservabile] (http://www.ittc.ku.edu/~andygill/papers/reifyGraph.pdf). – ehird

+0

Ho aggiornato il mio post con un esempio di quando 'reallyUnsafePtrEquality #' funzionerebbe ma 'StableName's no. – ehird

Problemi correlati