2011-12-25 13 views
16

Questo codice perdite di memoria (molto veloce, essere pronti a ucciderlo presto se lo provate):Perché nidificato per sempre perde memoria?

import Control.Monad (forever) 

main = do 
    forever $ forever $ return() 

(Compilato con -O2, -O, -O0 ..., GHC 7.0.3) Non capisco perché dovrebbe questa perdita - Sto usando un bel po 'di codice con gestore di eccezioni tra il per sempre e non capisco perché questo dovrebbe far perdere memoria ..

Ho appena cercato nella fonte per Control.Monad e trovato questo:

{- Note [Make forever INLINABLE] 

If you say x = forever a 
you'll get x = a >> a >> a >> a >> ... etc ... 
and that can make a massive space leak (see TraC#5205) 

In some monads, where (>>) is expensive, this might be the right 
thing, but not in the IO monad. We want to specialise 'forever' for 
the IO monad, so that eta expansion happens and there's no space leak. 
To achieve this we must make forever INLINABLE, so that it'll get 
specialised at call sites. 

Still delicate, though, because it depends on optimisation. But there 
really is a space/time tradeoff here, and only optimisation reveals 
the "right" answer. 
-} 

Questo bug è presumibilmente "riparato"; sfortunatamente sembra che il nidificato innesca per sempre il baco. È interessante notare che questa definizione di sempre (preso in prestito da Control.Monad) innesca l'errore:

forever a = a >> forever a 

Mentre la seguente definizione funziona senza problemi:

forever a = a >>= \_ -> forever a 

C'è qualcosa di pesce nell'operatore >>, come ho questo codice sarebbe equivalente.

risposta

11

Stavi guardando l'ultima versione di base, che probabilmente non è quello che stai utilizzando. Lo forever nella versione 4.3.1.0 non utilizza INLINABLE. Se eseguo il tuo esempio con GHC 7.2.2 e base 4.4.1.0, non ho perdite di spazio.

+0

Ok, quindi questo sembra essere risolto in 7.2.2. Sfortunatamente la piattaforma haskell sembra utilizzare 7.0.4, e ho 7.0.3 nella mia Ubuntu :(Dovrò trovare un modo per installare la versione più recente. – ondra

+2

Non hai davvero bisogno della piattaforma Haskell, se installi GHC 7.2. 2 e cabal-install (vedi [istruzioni speciali per GHC 7.2 qui] (https://gist.github.com/1169332), nota: questo funziona su ogni piattaforma, non solo su OS X) puoi 'cabal installare' qualsiasi pacchetto hai bisogno di te stesso Il valore della piattaforma Haskell deriva solo dall'essere precompilato e confezionato. – ehird

Problemi correlati