【问题标题】:Memory blowing up for strict sum/strict foldl in ghcighci 中的严格 sum/strict foldl 内存爆炸
【发布时间】:2014-07-19 09:47:07
【问题描述】:

正如Why does (sum $ takeWhile (<10000000) [1..]) use so much memory? 中提到的,以下确实不会炸毁 ghci 中的内存:

foldl' (+) 0 $ takeWhile (< 10000000) [1 .. ]

但是,如果我创建一个包含以下内容的文件:

import Data.List

longList::[Int]
longList = [1 .. ]

result :: Int
result = foldl' (+) 0 $ takeWhile (< 10000000) longList

main = do
  print $ result

并加载到 ghci,然后在运行程序时内存消耗会爆炸。为什么会这样,我能做些什么来修复程序?我正在使用 ghc 7.8.3。

[编辑]

如果我首先通过ghc Test.hs 编译,它确实似乎会爆炸。但是如果我删除所有.hi.o 文件,并通过ghci Test.hs 加载到ghci 中,那么内存确实会爆炸。

【问题讨论】:

  • 我在 ghci 和编译和运行时都没有遇到这个程序的内存爆炸。我正在使用7.6.3。它是编译器错误吗?此外,您可能希望使用ghci -fobject-code 启动您的ghci,如here 所述。
  • @Sibi 我可以在7.6.3 中复制此内容。如果您删除所有.hi.o 文件,然后通过ghci Test.hs 加载到ghci 中,程序是否会为您炸毁?谢谢
  • @Sibi,奇怪的是,如果我先通过 ghc Test.hs 编译然后加载到 ghci 中它不会崩溃
  • 如果我删除它们并使用ghci 再次测试它,我会看到一些内存爆炸。我想最好不要在ghci 中测试这些条件。
  • 我回滚到以前的版本。我们不会在 Stack Overflow 上的问题中提供答案,因为与许多论坛不同,您不必涉足“我也是”和“有没有人解决这个问题”之类的问题来找到有效的答案。对提问者最有效的答案被绿色勾拉到顶部。

标签: haskell memory-leaks ghci


【解决方案1】:

我认为这是由于在 GHCi 中 :l 文件时标识符 longList 的处理方式与编译时不同。

当你在 GHCi 中 :l ModuleName 时,默认情况下 all 模块中的顶级标识符进入范围,以便你可以有效地调试它。对于您的示例,这包括 longList。这意味着 GHCi 在评估之后保留longList 的内容,这会导致内存泄漏。我怀疑即使 -fobjectcode 也是这种情况,所以我不确定其他 cmets 中讨论的行为实际上是一个错误。

相反,当您编译模块时,GHC 使用模块导出列表来找出结果中暴露了哪些标识符。由于您没有明确的 module 声明,因此默认为 (last paragraph)

module Main (main) where

这意味着在编译时,GHC 可以注意到除了main 之外的所有标识符都没有暴露,并且longList 只使用了一次。然后它可以放弃保持它的值,避免内存泄漏。

【讨论】:

  • 约翰森:非常感谢。添加module Main (main) where 然后加载到 ghci 解决了所有问题!:)
  • @artella 很高兴它有所帮助,尽管现在 很困惑,因为我刚刚说过这应该是默认行为!
  • 现在我发现我必须同时使用 module Main (main) whereghci -fobject-code Test (即您的答案和 Sibi 的答案的混合)。我认为当我写上面的评论时,我已经使用-fobject-code 做了一个 bashrc 别名,但没有意识到它是必要的。
  • nomeata 确认这是票证中的预期行为ghc.haskell.org/trac/ghc/ticket/9332
  • @artella 好吧,这更有意义,尽管我仍然认为module Main (main) where 不应该有所作为。我评论了trac。
【解决方案2】:

note on GHCI部分:

如果您在 GHCi 中运行代码时发现空间泄漏, 请注意,解释代码的行为与编译代码不同 代码:即使使用seq

考虑如下启动 ghci:

$ ghci -fobject-code

【讨论】:

  • 这对我不起作用。如果我删除所有.hi.o 文件,然后通过ghci -fobject-code Test.hs 加载,Linux 上的内存仍然会爆炸。
  • @artella 是的,-fobject-code 我还可以看到一些内存爆炸。这里的要点是在使用seq 时,最好将其编译为可执行文件然后运行它来进行测试。
  • 这很奇怪,因为使用-fobject-code 会创建.hi 文件和.o 文件,就像通过ghc Test.hs 编译一样。然而,对于前者,内存会爆炸,但如果我做后者然后加载到 ghci 内存不会爆炸。我只能猜测文件的生成方式不同
  • @artella 但是在使用-fobject-code 时仍然不应该发生这种情况。我不确定是什么导致了问题。可能会提交错误报告,因为您也可以在 7.8.3 上重现此问题?
  • 最后我发现我必须结合使用你的答案和 Orjan 的答案,以阻止它在 ghc 7.8.3 中爆炸。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-12
  • 1970-01-01
  • 2019-07-26
  • 2014-07-12
  • 1970-01-01
  • 1970-01-01
  • 2015-06-11
相关资源
最近更新 更多