readRawBufferPtr and writeRawBufferPtr allocate memory
I initially filed this as a question on StackOverflow, assuming that the behavior I'm seeing was intentional, or that I was misinterpreting the profiler results... but Kazu Yamamoto suggested I should file this as an issue here. It's my first GHC ticket, so here goes:
main :: IO ()
main = do
buf <- mallocArray 1
echo buf
echo :: Ptr Word8 -> IO ()
echo buf = forever $ do
len <- readRawBufferPtr "read" stdin buf 0 1
writeRawBufferPtr "write" stdout buf 0 (fromIntegral len)
I expect the only heap allocation here should be my explicit mallocArray
, but profiling with +RTS -P
indicates this isn't the case: both the read and write operations do appear to allocate some short-lived heap objects each time through the loop. (Note: this isn't a space leak, the allocated objects appear to be GC'ed quickly, whatever they are). In contrast:
echo :: Ptr Word8 -> IO ()
echo buf = forever $ do
threadWaitRead $ Fd 0
len <- c_read 0 buf 1
c_write 1 buf (fromIntegral len)
yield
does not appear to allocate.
I did a bit of digging (copying bits of source code from base
into my own project, to get cost center annotations) and it seems like the allocation might be happening in throwErrnoIfRetryMayBlock
. See this gist for more detail, including core output from -ddump-simpl
.
In all honesty, I don't know whether this is a bug. I was just surprised by it, when I first encountered it using hGetBuf
/ hPutBuf
, so I'm trying to understand whether this is expected behavior and why.