summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNiklas Hambüchen <mail@nh2.me>2017-02-11 19:24:30 -0500
committerBen Gamari <ben@smart-cactus.org>2017-02-11 19:58:35 -0500
commit805db96544111bd548c9a32488a9c97996cc2b49 (patch)
tree6a052e5a3b9424e9f2ae3013dd21a6843ed45d49
parent4e2e9b7324e253295613fe868a281e1801e05d10 (diff)
downloadhaskell-805db96544111bd548c9a32488a9c97996cc2b49.tar.gz
Fix: hPutBuf issues unnecessary empty write syscalls for large writes (#13246)
Until now, any `hPutBuf` that wrote `>= the handle buffer size` would trigger an unnecessary `write("")` system call before the actual write system call. This is fixed by making sure that we never flush an empty handle buffer: Only flush `when (w > 0)`. Reviewers: simonmar, austin, hvr, bgamari Reviewed By: bgamari Subscribers: thomie Differential Revision: https://phabricator.haskell.org/D3119
-rw-r--r--libraries/base/GHC/IO/Handle/Text.hs13
1 files changed, 8 insertions, 5 deletions
diff --git a/libraries/base/GHC/IO/Handle/Text.hs b/libraries/base/GHC/IO/Handle/Text.hs
index 4a5e4cf6e6..c53b4294b8 100644
--- a/libraries/base/GHC/IO/Handle/Text.hs
+++ b/libraries/base/GHC/IO/Handle/Text.hs
@@ -745,11 +745,14 @@ bufWrite h_@Handle__{..} ptr count can_block =
writeIORef haByteBuffer old_buf{ bufR = w + count }
return count
- -- else, we have to flush
- else do debugIO "hPutBuf: flushing first"
- old_buf' <- Buffered.flushWriteBuffer haDevice old_buf
- -- TODO: we should do a non-blocking flush here
- writeIORef haByteBuffer old_buf'
+ -- else, we have to flush any existing handle buffer data
+ -- and can then write out the data in `ptr` directly.
+ else do -- No point flushing when there's nothing in the buffer.
+ when (w > 0) $ do
+ debugIO "hPutBuf: flushing first"
+ flushed_buf <- Buffered.flushWriteBuffer haDevice old_buf
+ -- TODO: we should do a non-blocking flush here
+ writeIORef haByteBuffer flushed_buf
-- if we can fit in the buffer, then just loop
if count < size
then bufWrite h_ ptr count can_block