大型HTTP响应主体的Haskell快照内存使用
我试图使用Haskell Snap框架提供一个大型HTTP响应,但是内存使用量会随着响应的大小而成比例增长。下面是几个使用大型lazy ByteString的精简测试用例:大型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
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,我已经按照您的建议更新了代码。