生成不同整数的树会导致空间泄漏

时间:2015-12-24 12:38:35

标签: haskell memory-leaks profiling

我想生成一个包含不同整数的树并找到它们的总和。这是代码:

{-# LANGUAGE BangPatterns #-}

import Control.Applicative
import Control.Monad.Trans.State

data Tree a = Leaf a | Branch (Tree a) a (Tree a)

new = get <* modify' (+ 1)

tree :: Integer -> Tree Integer
tree n = evalState (go n) 0 where
    go 0 = Leaf <$> new
    go n = Branch <$> go (n - 1) <*> new <*> go (n - 1)

sumTree = go 0 where
    go !a (Leaf n)       = a + n
    go !a (Branch l n r) = go (go (a + n) l) r

main = print $ sumTree (tree 20)

使用-O2编译,结果为

     348,785,728 bytes allocated in the heap
     147,227,228 bytes copied during GC
      34,656,860 bytes maximum residency (13 sample(s))
          35,468 bytes maximum slop
              72 MB total memory in use (0 MB lost due to fragmentation)

                                     Tot time (elapsed)  Avg pause  Max pause
  Gen  0       565 colls,     0 par    0.764s   1.024s     0.0018s    0.0071s
  Gen  1        13 colls,     0 par    0.936s   1.014s     0.0780s    0.3214s

  INIT    time    0.000s  (  0.001s elapsed)
  MUT     time    0.936s  (  0.764s elapsed)
  GC      time    1.700s  (  2.038s elapsed)
  EXIT    time    0.000s  (  0.002s elapsed)
  Total   time    2.636s  (  2.805s elapsed)

  %GC     time      64.5%  (72.7% elapsed)

  Alloc rate    372,631,936 bytes per MUT second

  Productivity  35.5% of total user, 33.4% of total elapsed

为什么我会漏这个空间?如何删除它?

1 个答案:

答案 0 :(得分:1)

每当你构建一棵树时,你应该尝试从上到下专门找到一种工作方式。这通常适用于懒惰,并发,缓存利用率,GC效率等。您构建的树只是按顺序编号的完整二叉树。我建议你考虑使用以下签名并做一些改变:

tree :: Bits b => Int -> Tree b

你可以打破一个起点的辅助函数。