GHCI似乎在交互式会话期间缓存函数的结果。很容易注意到,只需要两次调用一个耗时的功能。第二次,结果将立即显示。
有没有办法从GHCI中清除此缓存,所以我不必重新启动它?我正在进行一些快速的非详细性能比较,因此使用System.CPUTime会有点矫枉过正。
答案 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年答案:不可能...