如何清除ghci的函数结果缓存?

时间:2013-03-18 18:03:49

标签: haskell ghci

GHCI似乎在交互式会话期间缓存函数的结果。很容易注意到,只需要两次调用一个耗时的功能。第二次,结果将立即显示。

有没有办法从GHCI中清除此缓存,所以我不必重新启动它?我正在进行一些快速的非详细性能比较,因此使用System.CPUTime会有点矫枉过正。

5 个答案:

答案 0 :(得分:14)

您始终可以通过命令:r重新加载您正在使用的模块。这将丢弃你所做的任何交互式绑定,如果你只是在四处寻找,这可能并不总是实用的。如果您实际上没有使用模块,这也可以。

答案 1 :(得分:4)

正如评论所述,您正在使用let名称绑定到,这是应用的结果>一个功能。如果你想保持价值,不要在let中命名! (或者只是不要引用你在let中计算过的值)。

答案 2 :(得分:3)

GHCi有一个+r选项,according to the manual,应该做你想做的事情:

  

通常,对顶级表达式的任何评估(也称为   保留已加载模块中的CAF或常量应用表单   评估之间。启用+r会导致对顶级的所有评估   每次评估后要丢弃的表达式(它们仍然是   在单一评估中保留。)

     

如果评估的顶级表达式是,则此选项可能会有所帮助   消耗大量空间,或者如果你需要可重复的话   性能测量。

请注意,它会讨论constant applicative forms,而不是函数。但是,我无法让它为你的例子工作:

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)

显然,+r only works for compiled code,虽然文档没有提到这一点。

答案 3 :(得分:2)

总结一下,

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

让我们开始测试,

>>> 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)

使用undefined,

>>> 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'

重置绑定,

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

另一个研究案例,

>>> 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)

仍然缓存,更改h的绑定以查看,

>>> 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'

不管怎样,还需要重新定义f,

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

使用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'

答案 4 :(得分:0)

2019年答案:不可能...