为什么这个Haskell程序在使用优化编译时会泄漏空间?
考虑下面的玩具程序,它计算一个字中所有字符替换的组合,这是密码中经常使用的类型为什么这个Haskell程序在使用优化编译时会泄漏空间?,haskell,optimization,memory-leaks,ghc,Haskell,Optimization,Memory Leaks,Ghc,考虑下面的玩具程序,它计算一个字中所有字符替换的组合,这是密码中经常使用的类型 import Data.Char (isLower, toUpper) variants :: String -> [String] variants "" = [""] variants (c:s) = [c':s' | c' <- subst c, s' <- variants s] where subst 'a' = "aA@" subst 'e' = "eE3"
import Data.Char (isLower, toUpper)
variants :: String -> [String]
variants "" = [""]
variants (c:s) = [c':s' | c' <- subst c, s' <- variants s]
where subst 'a' = "aA@"
subst 'e' = "eE3"
subst 'i' = "iI1"
subst 'l' = "lL1"
subst 'o' = "oO0"
subst 's' = "sS$5"
subst 'z' = "zZ2"
subst x | isLower x = [x, toUpper x]
subst x = [x]
main :: IO ()
main = putStrLn $ show $ length $ variants "redistributables"
现在test0
和test1
产生相同的输出,但是test1
使用了更多的内存,并将大部分时间用于垃圾收集:
$ ./test0 +RTS -s 2>&1 | grep total
2 MB total memory in use (0 MB lost due to fragmentation)
Productivity 93.2% of total user, 93.3% of total elapsed
$ ./test1 +RTS -s 2>&1 | grep total
188 MB total memory in use (0 MB lost due to fragmentation)
Productivity 15.0% of total user, 15.0% of total elapsed
为什么?
我使用的是GHC 7.4.1;我可能应该使用一个更新的编译器,但这是我目前手头上的东西,不管怎样,问题可能出在我身上。诀窍是导致后缀重新计算,而不是保留在内存中。这就像是和
powerset (x:xs) = map (x:) (powerset xs) ++ powerset xs
定义,其中添加where
子句是有害的(或者它是powerset(x:xs)=powerset xs++map(x:)(powerset xs)
…)
在您的情况下,要尝试的代码是mapM subst
,或者
variants (c:cs) = variants cs >>= \s-> map (:s) (subst c)
从列表理解代码中可以看出,后一种方法的工作方向与“相反”,因此
variants (c:s) = [c':s' | s' <- variants s, c' <- subst c]
variants(c:s)=[c':s'| s'您想要的
variants (c:s) = [c':s' | c' <- subst c, s' <- variants s]
变体(c:s)=[c':s'| c'7.4在这一点上非常古老,如果不是7.10,至少使用7.8。要回答这个问题,您可能需要通过-ddump siml
来获得核心输出,然后通过它来准确地找出区别。@bheklir这样做了。当然,生成的核心非常不同,但对于Ha来说确实很难skell新手需要解开,到目前为止,我还没有成功。@WillNess-fn完全的懒惰没有什么区别。@WillNess前者会做,后者不会。诀窍是导致后缀重新计算,而不是保留在内存中。这就像powerset(x:xs)=map(x:)(powerset xs)++powerset xs
定义,在其中添加子句是有害的。(或者它是powerset(x:xs)=powerset xs++map(x:)(powerset xs)
?)实际上,交换c'
variants (c:s) = [c':s' | c' <- subst c, s' <- variants s]