-
Notifications
You must be signed in to change notification settings - Fork 47
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reduce system call overhead of copyFile
by increasing the buffer size to 128 KiB
#69
Conversation
…ze to 128 KiB. 128 KiB is what coreutils `cp` uses, based on a benchmark provided here: http://git.savannah.gnu.org/cgit/coreutils.git/tree/src/ioblksize.h?id=c0a79542fb5c2c22cf0a250db94af6f8581ca342#n23 The benchmarks report speedups of factor 5x to 30x depending on the hardware.
I'd still like somebody to independently verify the gains. |
Also, there's some weird thing going on with
This happens as soon as you set With 8095 or smaller, it looks right like:
|
Have you tried disabling buffering perhaps? |
I can't seem to figure out whether |
@Rufflewind Yes, I had, to no avail; tried with |
What I find especially disturbing is that the |
This leads me to the suspicion that this might be going on in |
Minimal example: import Foreign.Marshal.Alloc (allocaBytes)
import System.IO
main = do
withBinaryFile "testfile2" WriteMode $ \ hTo -> do
let bufferSize = 8096 -- write("") is gone when we use 8095 here
allocaBytes bufferSize $ \buffer -> do
hPutBuf hTo buffer bufferSize In
|
OK, making some progress here. The 8096 comes from https://hackage.haskell.org/package/base-4.9.1.0/docs/src/GHC.IO.FD.html#dEFAULT_FD_BUFFER_SIZE instance BufferedIO FD where
newBuffer _dev state = newByteBuffer dEFAULT_FD_BUFFER_SIZE state
-- We used to use System.Posix.Internals.dEFAULT_BUFFER_SIZE, which is
-- taken from the value of BUFSIZ on the current platform. This value
-- varies too much though: it is 512 on Windows, 1024 on OS X and 8192
-- on Linux. So let's just use a decent size on every platform:
dEFAULT_FD_BUFFER_SIZE :: Int
dEFAULT_FD_BUFFER_SIZE = 8096 Does anybody know why |
OK it's all clear now, it's a typo in the number indeed, will post an update shortly. The There's also an unrelated |
OK, I've written this up as GHC bugs:
and filed a third slightly related |
This PR can now return to its original purpose, increasing the |
I've done some quick Preparing a 1GB file:
Code:
(running on a version of Because of the Running with GHC 8.0.2 on Stackage
As you can see, These measurements support that |
I should also mention, this change makes
The only thing that's faster is
|
To answer the other question:
@erikd It doesn't, |
Tested this on tmpfs (ramdisk) and SSD on my Linux machine, and there was a speedup of ~60%. The results fluctuates a lot on my machine. Generally I expect it to different from OS to OS depending on how well the OS caches the I/O. In any case, I don't doubt that this should be speed increase in the majority of cases given how large I/O caches have become these days. Will merge shortly.
It's probably better to use
In the future, it'd be nice to use |
Thanks for the PR and the benchmarks! |
It's a bit slow due to the `copyFile` bug haskell/directory#69 and this GHC bug: https://ghc.haskell.org/trac/ghc/ticket/13246
128 KiB is what coreutils
cp
uses, based on a benchmark provided here:http://git.savannah.gnu.org/cgit/coreutils.git/tree/src/ioblksize.h?id=c0a79542fb5c2c22cf0a250db94af6f8581ca342#n23
The benchmarks report speedups of factor 5x to 30x depending on
the hardware.