为什么这段代码在内存中变得如此之大?

时间:2018-01-27 07:35:18

标签: performance haskell

如果我使用crash和50000000(五千万)的任何值调用increment进行旋转,它会逐渐增加并保持内存大小增长,直到每个内存都被阻塞然后崩溃。

crash :: Int -> Int -> Int 
crash increment spins = snd $ foldl' spin' (0,0) [1..spins]
  where spin' = spin increment

spin increment (index,element1) spinNumber = (next,nextElementOne)
  where
    next 
      | indexNIncrement >= spinNumber = 1 + (indexNIncrement `rem` spinNumber)
      | otherwise = 1 + indexNIncrement
    indexNIncrement = index + increment
    nextElementOne
      | next==1 = spinNumber
      | otherwise = element1

我不知道内存是如何泄露的。是否每次调用spin都会替换累加器值?它不会被释放吗?

1 个答案:

答案 0 :(得分:3)

基本上,在每个步骤foldl'将在每一步评估函数spin'的结果,将其带到WHNF(弱头正常形式)。具体来说,这意味着将在第一个构造函数之前评估结果。

然而,spin'的结果是(next,nextElementOne),它已经在WHNF中,因为它以一对构造函数开头。我们想要的是在这里强制评估对组件。一个基本的解决方案是返回

spin ... = next `seq` (nextElementOne `seq` (next, nextElementOne))

以便在返回对之前评估组件。

更现代的方法可能是利用BangPatterns