大型HTTP响应主体的Haskell快照内存使用

大型HTTP响应主体的Haskell快照内存使用,haskell,memory-leaks,haskell-snap-framework,Haskell,Memory Leaks,Haskell Snap Framework,我试图使用Haskell Snap框架提供一个大型HTTP响应,但是内存使用量会随着响应的大小而成比例增长。下面是几个使用大型lazy ByteString的精简测试用例: import Snap.Core (Snap, writeLBS, readRequestBody) import Snap.Http.Server (quickHttpServe) import Control.Monad.IO.Class (MonadIO(liftIO)) import qualified Data.B

我试图使用Haskell Snap框架提供一个大型HTTP响应,但是内存使用量会随着响应的大小而成比例增长。下面是几个使用大型lazy ByteString的精简测试用例:

import Snap.Core (Snap, writeLBS, readRequestBody)
import Snap.Http.Server (quickHttpServe)
import Control.Monad.IO.Class (MonadIO(liftIO))
import qualified Data.ByteString.Lazy.Char8 as LBS (ByteString, length, replicate)

main :: IO ()
main = quickHttpServe $ site test1 where
    test1, test2 :: LBS.ByteString -> Snap ()

    -- Send ss to client
    test1 = writeLBS

    -- Print ss to stdout upon receiving request
    test2 = liftIO . print

    site write = do
        body <- readRequestBody 1000
        -- Making ss dependant on the request stops GHC from keeping a
        -- reference to ss as pointed out by Reid Barton.
        let bodyLength = fromIntegral $ LBS.length body
        write $ ss bodyLength

    ss c = LBS.replicate (1000000000000 * (c + 1)) 'S'
导入Snap.Core(Snap、writeLBS、readRequestBody) 导入Snap.Http.Server(quickHttpServe) 进口管制.Monad.IO.Class(MonadIO(liftIO)) 将限定的Data.ByteString.Lazy.Char8作为LBS导入(ByteString、length、replicate) main::IO() main=quickHttpServe$site test1其中 test1、test2::LBS.ByteString->Snap() --发送ss到客户端 test1=writeLBS --收到请求后将ss打印到标准输出 test2=liftIO。打印 站点写入=do
body您是如何测量内存使用率的?在linux上使用“top”即可。它使用我机器上的所有内存(16gb)并开始交换。值
ss
在请求之间共享,因此它的内存表示形式将随着第一个请求的计算而增加,以便可以在以后的请求中重用
test3
没有这种行为,因为它只使用
ss
一次,所以可以丢弃已使用的块。(但是请尝试
test4=print ss>>print ss
)您应该在处理程序中定义
ss
,并使其以某种方式取决于请求,以阻止GHC将其浮动。谢谢Reid,这很有意义。如果我将ss参数化为请求的长度,我将更新问题,因为问题仍然存在。@ReidBarton,我已经按照您的建议更新了代码。