gpt4 book ai didi

haskell - 管道:产生内存泄漏

转载 作者:行者123 更新时间:2023-12-05 00:19:16 27 4
gpt4 key购买 nike

在对上一个问题 (haskell-data-hashset-from-unordered-container-performance-for-large-sets) 进行一些观察时,我偶然发现了一个奇怪的内存泄漏

module Main where

import System.Environment (getArgs)
import Control.Monad.Trans.Resource (runResourceT)
import Data.Attoparsec.ByteString (sepBy, Parser)
import Data.Attoparsec.ByteString.Char8 (decimal, char)
import Data.Conduit
import qualified Data.Conduit.Attoparsec as CA
import qualified Data.Conduit.Binary as CB
import qualified Data.Conduit.List as CL

main :: IO ()
main = do (args:_) <- getArgs
writeFile "input.txt" $ unlines $ map show [1..4 :: Int]
case args of "list" -> m1
"fail" -> m2
"listlist" -> m3
"memoryleak" -> m4
--UPDATE
"bs-lines":_ -> m5
"bs":_ -> m6
_ -> putStr $ unlines ["Usage: conduit list"
," fail"
," listlist"
," memoryleak"
--UPDATE
," bs-lines"
," bs"
]
m1,m2,m3,m4 :: IO ()
m1 = do hs <- runResourceT
$ CB.sourceFile "input.txt"
$$ CB.lines
=$= CA.conduitParser (decimal :: Parser Int)
=$= CL.map snd
=$= CL.consume
print hs
m2 = do hs <- runResourceT
$ CB.sourceFile "input.txt"
$$ CA.conduitParser (decimal :: Parser Int)
=$= CL.map snd
=$= CL.consume
print hs
m3 = do hs <- runResourceT
$ CB.sourceFile "input.txt"
$$ CB.lines
=$= CA.conduitParser (decimal `sepBy` (char '\n') :: Parser [Int])
=$= CL.map snd
=$= CL.consume
print hs
m4 = do hs <- runResourceT
$ CB.sourceFile "input.txt"
$$ CA.conduitParser (decimal `sepBy` (char '\n') :: Parser [Int])
=$= CL.map snd
=$= CL.consume
print hs
-- UPDATE
m5 = do inpt <- BS.lines <$> BS.readFile "input.txt"
let Right hs = mapM (parseOnly (decimal :: Parser Int)) inpt
print hs
m6 = do inpt <- BS.readFile "input.txt"
let Right hs = (parseOnly (decimal `sepBy` (char '\n') :: Parser [Int])) inpt
print hs

这是一些示例输出:

$ > stack exec -- example list
[1234]
$ > stack exec -- example listlist
[[1234]]
$ > stack exec -- conduit fail
conduit: ParseError {errorContexts = [], errorMessage = "Failed reading: takeWhile1", errorPosition = 1:2}
$ > stack exec -- example memoryleak
(Ctrl+C)

-- UPDATE
$ > stack exec -- example bs-lines
[1,2,3,4]
$ > stack exec -- example bs
[1,2,3,4]

现在我的问题是:

  • 为什么 m1 不生成 [1,2,3,4]
  • 为什么 m2 失败了?
  • 为什么 m4 的行为与所有其他版本完全不同并产生空间泄漏?

最佳答案

Why is m2 failing?

作为字符流的输入文件是:

1\n2\n3\n4\n

由于 decimal 解析器不期望换行符,在使用第一个数字后剩余的流是:

\n2\n3\n4\n

由于输入流没有耗尽,conduitParser 将再次在流上运行解析器,这次它甚至无法消耗第一个字符,因此失败。

Why is m4 behaving totally different compared to all other versions and producing a space leak?

decimal `sepBy` (char '\n') 只会消耗两个整数之间的\n,成功解析四个数字后,输入流只有一个字符其中:

\n

decimal `sepBy` (char '\n') 不能使用它,更糟糕的是它不会失败:sepBy 可以不使用任何东西并返回空列表。因此它不会无限地解析任何东西并且永远不会终止。

Why is m1 not producing [1,2,3,4]?

我也想知道!我猜这与融合有关,也许你应该联系刚刚评论你的问题的 conduit package 的作者。

关于haskell - 管道:产生内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36254752/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com