I'm writing a network file transfer application. Using Lazy ByteString as a intermediate
import qualified Data.ByteString.Lazy as BSL
When constructing a BSL from local file, then put the BSL to a Handle of Socket:
BSL.readFile filename >>= BSL.hPut remoteH -- OK
This works fine. Memory usage is constant. But for receiving data from Socket, then write to local file:
BSL.hGet remoteH size >>= BSL.hPut fileH bs -- starts swapping in 1 second
I can see memory usage keep going up, BSL takes size bytes of memory. Worse, for large size that exceeded my physical memory size, OS starts swapping immediately.
I have to receive segments of ByteStrings recursively. That is OK.
Why BSL behave like that?
hGetis strict -- it immediately demands the number of bytes you requested. It does this in order to facilitate packet level reading of data.However,
hGetContentsNis lazy, andreadFileis implemented in terms ofhGetContentsN.Consider the two implementations:
and
The key magic is the laziness in
hGetContentsN.