haskell - 此代码中的空间泄漏在哪里?

标签 haskell memory-leaks

我试图通过交替行将一个文件拆分为两个单独的文件。 (即第 1、3、5、7 行...写入文件 1,第 2、4、6、8 行...写入文件 2)。

我正在处理的文件约为 700MB,所以当我看到超过 6GB 的内存使用气球时,我知道出了点问题。

main :: IO()
main = withFile splitFile ReadMode splitData
  where
    splitData h = do
      dataSet <- lines <$> hGetContents h
      let (s1,s2) = foldl' (\(l,r) x -> (x:r,l)) ([],[]) dataSet
      writeFile testFile $ unlines s1
      writeFile trainingFile $ unlines s2

我最初使用的是 foldl 的惰性版本,但经过一些研究,似乎使用严格版本会有所帮助。但是,唉,它没有明显的区别。我还尝试使用 -O2 进行编译,但这也没有任何作用。

我正在使用 GHC 7.10.2

我没有遇到堆栈溢出,那么它为什么要使用所有内存?

最佳答案

正如@dfeuer 在评论中提到的,writeFile 的使用将强制写入要计算的整个字符串,这也会强制读取整个输入。空间泄漏是由于在写入第一个文件时必须将整个第二个文件保存在内存中,而很明显一次只能在内存中保存一行。事实上,解决方案是逐行编写:

import Control.Monad 
import System.IO 

main :: IO ()
main = 
  withFile splitFile ReadMode $ \hIn ->  
  withFile testFile WriteMode $ \hOdd ->  
  withFile trainingFile WriteMode $ \hEven ->         
  zipWithM_ hPutStrLn (cycle [hOdd, hEven]) . lines =<< hGetContents hIn

这个程序在常量空间中运行。

关于haskell - 此代码中的空间泄漏在哪里?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36758778/

相关文章:

haskell - 在 Haskell 中寻找一种更惯用和更简短的编写平衡二叉树插入的方法

haskell - 引用存在类型变量

c# - 内存泄漏问题。使用 OpenCVSharp 在 Unity 中进行眼动追踪

c - 观察 Xcode Ansi C 中的内存分配

C:帮助查找内存故障

haskell - 仅保留在列表推导中多次出现的值

haskell - 概括没什么

javascript - 浏览器内存随着 javascript ajax 调用不断增加

arrays - 将字符串 char 设置为 null 会导致 C 中的内存泄漏吗?

haskell - 树折叠操作?