GHCI似乎在交互式會話期間緩存函數的結果。很容易注意到,只需調用一個耗時的函數兩次。第二次,結果會立即出現。如何清除ghci的函數結果緩存?
有沒有辦法從GHCI中清除這個緩存,所以我不必重新啓動它?我正在做一些quick'n'drty非詳細的性能比較,所以使用System.CPUTime而不是矯枉過正。
GHCI似乎在交互式會話期間緩存函數的結果。很容易注意到,只需調用一個耗時的函數兩次。第二次,結果會立即出現。如何清除ghci的函數結果緩存?
有沒有辦法從GHCI中清除這個緩存,所以我不必重新啓動它?我正在做一些quick'n'drty非詳細的性能比較,所以使用System.CPUTime而不是矯枉過正。
您可以隨時通過命令:r
重新加載正在使用的模塊。這將丟棄您製作的任何交互式綁定,如果您只是在四處漫遊,這可能並不總是實用。如果你實際上沒有使用模塊,這也可以工作。
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,雖然文檔沒有提到這一點。
總之,
>>> :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)
使用不確定,
>>> 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.
另一個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)
仍緩存,改變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 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'
你可以舉一個具體函數調用的例子嗎? – dave4420 2013-03-18 18:13:55
''讓f = 1:map(2 *)f''然後''last $ show $ f! 200000''。第一次,我的機器需要大約15秒,但是第二次立即計算。 – user42179 2013-03-18 18:30:34
這不是一個函數。 – 2013-03-18 18:31:14