gpt4 book ai didi

sockets - 从 Socket 句柄构建的惰性 ByteString 无法被延迟使用和 GC

转载 作者:行者123 更新时间:2023-12-02 16:53:22 24 4
gpt4 key购买 nike

我正在编写一个网络文件传输应用程序。使用 Lazy ByteString 作为中间体

import qualified Data.ByteString.Lazy as BSL

当从本地文件构造 BSL 时,然后将 BSL 放入 Socket 的句柄:

BSL.readFile filename >>= BSL.hPut remoteH  -- OK

这很好用。内存使用量是恒定的。但对于从Socket接收数据,然后写入本地文件:

BSL.hGet remoteH size >>= BSL.hPut fileH bs  -- starts swapping in 1 second

我可以看到内存使用量持续上升,BSL 占用了 size 字节的内存。更糟糕的是,对于超过我的物理内存大小的大大小,操作系统立即开始交换。

我必须递归地接收字节字符串段。没关系。

为什么BSL会有这样的行为?

最佳答案

hGet 是严格的——它立即要求您请求的字节数。这样做是为了促进数据包级别的数据读取。

但是,hGetContentsN 是惰性的,而 readFile 是根据 hGetContentsN 实现的。

考虑两种实现:

hGetContentsN :: Int -> Handle -> IO ByteString
hGetContentsN k h = lazyRead -- TODO close on exceptions
where
lazyRead = unsafeInterleaveIO loop

loop = do
c <- S.hGetSome h k -- only blocks if there is no data available
if S.null c
then do hClose h >> return Empty
else do cs <- lazyRead
return (Chunk c cs)

hGet :: Handle -> Int -> IO ByteString
hGet = hGetN defaultChunkSize

hGetN :: Int -> Handle -> Int -> IO ByteString
hGetN k h n | n > 0 = readChunks n
where
STRICT1(readChunks)
readChunks i = do
c <- S.hGet h (min k i)
case S.length c of
0 -> return Empty
m -> do cs <- readChunks (i - m)
return (Chunk c cs)

关键的魔力在于 hGetContentsN 中的惰性。

关于sockets - 从 Socket 句柄构建的惰性 ByteString 无法被延迟使用和 GC,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10649636/

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