haskell - 懒惰的字节串 : memory exploding in certain cases

标签 haskell lazy-evaluation

下面我们有两个看似功能相同的程序。第一个内存保持不变,而第二个内存爆炸(在 Ubuntu 14.04 64 位中使用 ghc 7.8.2 和 bytestring-0.10.4.0):

非爆炸:

--NoExplode.hs
--ghc -O3 NoExplode.hs
module Main where
import Data.ByteString.Lazy as BL
import Data.ByteString.Lazy.Char8 as BLC

num = 1000000000
bytenull = BLC.pack ""

countDataPoint arg sum
  | arg == bytenull = sum
  | otherwise = countDataPoint (BL.tail arg) (sum+1)

test1 = BL.last $ BL.take num $ BLC.cycle $ BLC.pack "abc" 
test2 = countDataPoint (BL.take num $ BLC.cycle $ BLC.pack "abc") 0

main = do
  print test1
  print test2

爆炸:
--Explode.hs
--ghc -O3 Explode.hs
module Main where
import Data.ByteString.Lazy as BL
import Data.ByteString.Lazy.Char8 as BLC

num = 1000000000
bytenull = BLC.pack ""

countDataPoint arg sum
  | arg == bytenull = sum
  | otherwise = countDataPoint (BL.tail arg) (sum+1)

longByteStr = BL.take num $ BLC.cycle $ BLC.pack "abc" 

test1 = BL.last $ longByteStr
test2 = countDataPoint (BL.take num $ BLC.cycle $ BLC.pack "abc") 0

main = do
  print test1
  print test2

其他详细信息:

不同之处在于 Explode.hs我已采取BL.take num $ BLC.cycle $ BLC.pack "abc"超出 test1 的定义,并将其分配给自己的值longByteStr .

奇怪的是,如果我们注释掉其中一个 print test1print test2Explode.hs (但显然不是两者),那么程序不会爆炸。

Explode.hs 中的内存爆炸是否有原因?而不是 NoExplode.hs ,以及为什么爆炸程序( Explode.hs )需要 print test1print test2为了爆发?

最佳答案

为什么ghc在一种情况下执行常用表达式消除,但在另一种情况下不执行?谁知道。也许是被内联杀死的常见表达式。基本上它取决于内部实现。

关于-ddump-simp ,请参阅这个 SO 问题:Reading GHC Core

我用 ghc-7.8.2 复制了它.它执行通用表达式消除。您可以检查 -ddump-simpl 的输出.所以你实际上创建了一个惰性字节串。

在第一个版本中,您创建了两个惰性字节串。 print test1强制第一个,但它是动态收集的垃圾,因为没有其他人使用它。 print test2 也是如此-- 它强制使用第二个字节串,并且它是动态 GC 的。

在第二个版本中,您创建一个惰性字节串。 print test1强制它,但它不能被 GC 处理,因为 print test2 需要它.结果,在第一个 print 之后您已将整个字节串加载到内存中。

如果您删除一个 print , 字节串再次被动态 GC。因为它没有在其他任何地方使用。

PS。 “GC'ed on the fly”的意思是:print获取第一个 block 并将其输出到 stdout .该 block 可用于 GC。然后prints取第二 block ,等等......

关于haskell - 懒惰的字节串 : memory exploding in certain cases,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24289369/

相关文章:

haskell - 检查数组在 Haskell 中 sum(x_0, x_1...x_k) == sum(x_k+1,..x_n) 是否相等

haskell - 我怎样才能触发我的规则?

haskell - 评估策略

haskell - 使用 haskell 项目 Euler prob 10

haskell - 使用 repa 计算图像直方图

haskell - 包含在元组中的更新列表

haskell - 免费 Monad 的 MonadError 实例

ios - 如何防止在 Swift 中延迟加载静态变量

haskell - Haskell 的 'seq' 与其他函数有何不同?

haskell - 关于懒惰的困惑