Подтвердить что ты не робот

Как очистить кеш-память функции ghci?

GHCI, похоже, кэширует результаты функций во время интерактивного сеанса. Легко заметить, просто дважды вызовите трудоемкую функцию. Во второй раз результат появится сразу.

Есть ли способ очистить этот кеш из GHCI, поэтому мне не нужно его перезапускать? Я делаю несколько быстрых нечетких сравнений производительности, поэтому использование System.CPUTime вместо этого будет излишним.

4b9b3361

Ответ 1

Вы всегда можете перезагрузить модуль, с которым работаете, с помощью команды :r. Это избавит вас от любых интерактивных привязок, которые вы сделали, и это может быть не всегда практичным, если вы просто ковыряетесь. Это также работает, если вы фактически не используете модуль.

Ответ 2

Как отмечается в примечании, вы используете let для привязки имени к значению, которое является результатом применения функции. Если вы хотите сохранить ценность вокруг, не называйте ее в let! (или просто не ссылайтесь на значение, которое вы уже вычислили в let).

Ответ 3

GHCi имеет параметр +r, который в соответствии с руководством должен делать то, что вы хотите:

Обычно любая оценка выражений верхнего уровня (иначе известная как CAF или константные аппликативные формы) в загруженных модулях сохраняется между оценками. Включение +r вызывает всю оценку верхнего уровня выражения, которые следует отбрасывать после каждой оценки (они все еще остаются сохраняются во время одной оценки).

Этот параметр может помочь, если оцененные выражения верхнего уровня потребляя большие объемы пространства, или если вам требуется повторяемость измерения производительности.

Обратите внимание, что он говорит о постоянных аппликативных формах, а не о функциях. Однако я не мог заставить его работать для вашего примера:

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 работает только для скомпилированного кода, хотя документы не упоминают об этом.

Ответ 4

Подводя итог,

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

reset привязка,

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