Sto cercando di modificare la monade Data.Binary.PutM in un trasformatore monad. Così ho iniziato da changin di essa la definizione dallaPerché la modifica della monade Data.Binary.Put in un trasformatore crea una perdita di memoria?
newtype PutM a = Put { unPut :: PairS a }
a
newtype PutM a = Put { unPut :: Identity (PairS a) }
Poi, naturalmente, ho cambiato l'implementazioni di ritorno e >> = funzioni:
Da:
return a = Put $ PairS a mempty
{-# INLINE return #-}
m >>= k = Put $
let PairS a w = unPut m
PairS b w1 = unPut (k a)
in PairS b (w `mappend` w1)
{-# INLINE (>>=) #-}
m >> k = Put $
let PairS _ w = unPut m
PairS b w1 = unPut k
in PairS b (w `mappend` w1)
{-# INLINE (>>) #-}
A:
return a = Put $! return $! PairS a mempty
{-# INLINE return #-}
m >>= k = Put $!
do PairS a w <- unPut m
PairS b w1 <- unPut (k a)
return $! PairS b $! (w `mappend` w1)
{-# INLINE (>>=) #-}
m >> k = Put $!
do PairS _ w <- unPut m
PairS b w1 <- unPut k
return $! PairS b $! (w `mappend` w1)
{-# INLINE (>>) #-}
Come se la monade PutM fosse solo una monade Scrittore. Sfortunatamente questo (again) ha creato una perdita di spazio. È chiaro per me (o è?) Che ghc sta posticipando la valutazione da qualche parte, ma ho provato a inserire $!
invece di $
ovunque come suggerito da alcuni tutorial, ma questo non ha aiutato. Inoltre, non sono sicuro di come sia utile il profiler di memoria se ciò che mi viene mostrato è questo:
.
E per completezza, questo è il profilo di memoria ottengo quando si utilizza la monade Data.Binary.Put originale:
Se interessati, here è il codice che sto usando per testarlo e la linea che sto usando per compilare, eseguire e creare il profilo di memoria è:
ghc -auto-all -fforce-recomp -O2 --make test5.hs && ./test5 +RTS -hT && hp2ps -c test5.hp && okular test5.ps
Spero che non sono fastidioso chiunque dalla mia saga di domande di perdita di memoria. Trovo che non ci siano molte buone risorse su internet su questo argomento che lasciano un nuovo addio all'oscuro.
Grazie per la ricerca.
Ciao Peter - Non sono convinto che tu abbia una "perdita di spazio" all'interno di Data.Binary, ad es.alcuni gesti errati sui dati che lo bloccano. Penso che il motivo per cui stai costruendo un enorme profilo di memoria sia dovuto al fatto che la struttura dei dati (una struttura ad albero) non viene trasmessa in streaming - tutto deve essere in memoria (oltre a un ByteString output di grandi dimensioni simile) fino al completamento della serializzazione. La mia intuizione è che il problema è l'albero - non DataBinary. –
Salve @stephen, ho dimenticato di menzionare che se uso il monad Data.Binary.Put originale (quello senza Identity in esso), allora sta fluendo bene (nessun aumento di memoria notevole). La mia comprensione è che se la memoria fosse stata consumata esclusivamente dalla struttura ad albero, l'aumento della memoria si sarebbe manifestato in entrambi i casi. –
Potresti inviarci altro codice? – fuz