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.