Iva*_*yuk 2 haskell memory-leaks tail-recursion
我正在处理Haskell程序中的内存泄漏,并且能够将其隔离为处理数组时非常基本的惰性问题。我了解那里发生了什么。数组的第一个元素被计算,其余的则产生延迟的计算,这消耗了堆。不幸的是,我无法对整个数组计算强制严格。
我尝试了seq,BangPatterns($!)的各种组合,但没有取得太大的成功。
import Control.Monad
force x = x `seq` x
loop :: [Int] -> IO ()
loop x = do
when (head x `mod` 10000000 == 0) $ print x
let x' = force $ map (+1) x
loop x'
main = loop $ replicate 200 1
Run Code Online (Sandbox Code Playgroud)
具有标准配置文件选项的配置文件没有提供我已经知道的更多信息:
ghc -prof -fprof-auto-calls -rtsopts test.hs
./test +RTS -M300M -p -hc
Run Code Online (Sandbox Code Playgroud)
这将在几秒钟内耗尽内存。
force x = x `seq` x
Run Code Online (Sandbox Code Playgroud)
没用 seq并不意味着“立即评估此事”;意思是“在返回正确的事物的结果之前先评估左边的事物”。当它们相同时,它什么都不做,而您force相当于just id。尝试以下方法:
import Control.DeepSeq
import Control.Monad
loop :: [Int] -> IO ()
loop x = do
when (head x `mod` 10000000 == 0) $ print x
let x' = map (+1) x
loop $!! x'
main = loop $ replicate 200 1
Run Code Online (Sandbox Code Playgroud)
这会进行评估x',然后评估其中的所有内容loop x',这很有用。
另外,Control.DeepSeq具有force有用的功能。在这种情况下,它的语义是“在返回评估结果之前,先评估列表中的所有元素”。如果您使用它的force功能代替自己的功能,那么原始代码将可以正常工作,因为的第一行loop确实会评估列表的开头。