2013-03-18 22 views
14

GHCI sembra memorizzare nella cache i risultati delle funzioni durante una sessione interattiva. È facile da notare, basta chiamare due volte una funzione che richiede tempo. Alla seconda volta, il risultato apparirà immediatamente.Come cancellare la cache dei risultati delle funzioni di ghci?

C'è un modo per svuotare questa cache dall'interno di GHCI quindi non devo riavviarlo? Sto facendo alcuni quick'n'dirty confronti di performance non dettagliati, quindi usare System.CPUTime sarebbe invece eccessivo.

+2

Potrebbe fornire un esempio di una funzione specifica chiamata che viene memorizzata nella cache, per favore? – dave4420

+0

'' let f = 1: map (2 *) f'' e quindi '' last $ show $ f !! 200000''. La prima volta, la macchina richiede circa 15 secondi, ma viene calcolata immediatamente la seconda volta. – user42179

+6

Questa non è una funzione. –

risposta

4

Come la nota commenti, si sta utilizzando let per associare un nome ad un valoreche è il risultato dell'applicazione di una funzione. Se vuoi mantenere il valore, non nominarlo in un let! (o semplicemente non fare riferimento al valore che hai già calcolato in un let).

+0

Questo non è sempre semplice - ad esempio, l'OP di esempio fornito è ricorsivo, quindi senza 'fix' è difficile definire senza' let' – amindfv

+5

'let f = foo f' darà un binding. 'let f = foo f in f' no. semplice! – sclv

13

È sempre possibile ricaricare il modulo su cui si sta lavorando tramite il comando :r. Questo eliminerà tutti i collegamenti interattivi che hai fatto, e questo potrebbe non essere sempre pratico se stai solo curiosando. Questo funziona anche se non stai effettivamente utilizzando un modulo.

3

GHCi ha un'opzione +r, che, according to the manual, dovrebbe fare quello che vuoi:

Normalmente, qualsiasi valutazione di espressioni di primo livello (altrimenti noto come CAF o forme applicative costanti) in moduli caricati è mantenuto tra le valutazioni. L'attivazione di +r causa l'annullamento di tutte le valutazioni delle espressioni di livello superiore dopo ogni valutazione (rimangono comunque mantenute durante una singola valutazione).

Questa opzione può essere d'aiuto se le espressioni di livello superiore valutate sono che consumano grandi quantità di spazio o se sono necessarie misurazioni di prestazioni ripetibili .

Si noti che si parla di constant applicative forms, non di funzioni. Tuttavia, non ho potuto farlo funzionare per il tuo esempio:

Prelude> :set +r 
Prelude> :set +s 
Prelude> let f = 1 : map (2*) f 
(0.01 secs, 1222216 bytes) 
Prelude> last $ show $ f !! 100000 
'6' 
(3.54 secs, 641914476 bytes) 
Prelude> last $ show $ f !! 100000 
'6' 
(0.04 secs, 1634552 bytes) 
Prelude> last $ show $ f !! 100000 
'6' 
(0.04 secs, 1603568 bytes) 

A quanto pare, +r only works for compiled code, anche se la documentazione non menzionano questo.

2

In sintesi,

>>> :set +s -- activate performance 
>>> :r  -- reset all interactive binding 
Ok, modules loaded: none. 
>>> :show bindings -- check the binding state 

Cominciamo il test,

>>> let f = 1 : map (2*) f 
(0.01 secs, 1543272 bytes) 
>>> :show bindings 
f :: [Integer] = _ 
>>> last $ show $ f !! 50000 
'6' 
(0.55 secs, 170011128 bytes) 
>>> :show bindings 
f :: [Integer] = 1 : 2 : 4 : 8 : 16 : .... 
it :: Char = '6' 
>>> last $ show $ f !! 50000 
'6' 
(0.02 secs, 1562456 bytes) 

Utilizzando indefinito,

>>> let f = undefined 
(0.01 secs, 565912 bytes) 
>>> :show bindings 
it :: Char = '6' 
f :: a = _ 
>>> let f = 1 : map (2*) f 
(0.01 secs, 513304 bytes) 
>>> last $ show $ f !! 50000 
'6' 
(0.94 secs, 170517840 bytes) 
>>> :show bindings 
f :: [Integer] = 1 : 2 : 4 : 8 : 16 : .... 
it :: Char = '6' 

resettare il legame,

>>> :r 
>>> :show bindings 
Ok, modules loaded: none. 

Un altro caso studie,

>>> let h = (2*) 
(0.01 secs, 590232 bytes) 
>>> let f = 1 : map h f 
(0.01 secs, 1138792 bytes) 
>>> :show bindings 
it :: Char = '6' 
h :: Integer -> Integer = _ 
f :: [Integer] = _ 
>>> last $ show $ f !! 60000 
'6' 
(1.69 secs, 241802432 bytes) 
>>> last $ show $ f !! 60000 
'6' 
(0.03 secs, 2002432 bytes) 

ancora nella cache, modificare il legame di h di vedere,

>>> let h = (3*) 
(0.01 secs, 547208 bytes) 
>>> last $ show $ f !! 60000 
'6' 
(0.03 secs, 2029592 bytes) 
>>> :show bindings 
f :: [Integer] = 1 : 2 : 4 : 8 : 16 : .... 
h :: Integer -> Integer = _ 
it :: Char = '6' 

fare, non importa, hanno bisogno di ridefinire f anche,

>>> let f = 1 : map h f 
(0.01 secs, 552048 bytes) 
>>> last $ show $ f !! 60000 
'1' 
(4.36 secs, 374064760 bytes) 

Utilizzo Let .. in ... binding,

>>> let f = let h = (2*) in 1 : map h f 
(0.02 secs, 1068272 bytes) 
>>> last $ show $ f !! 60000 
'6' 
(3.90 secs, 242190168 bytes) 
>>> last $ show $ f !! 60000 
'6' 
(4.89 secs, 242271560 bytes) 
>>> last $ show $ f !! 60000 
'6' 
(5.71 secs, 242196976 bytes) 
>>> :show bindings 
h :: Integer -> Integer = _ 
f :: Num a => [a] = _ 
it :: Char = '6' 
Problemi correlati