I am working on a REST API that has an endpoint to download a file that could be > 2 GB in size. I have read that Java's FileChannel.transferTo(...)
will use zero-copy if the OS supports it. My server is running on localhost during development on my MacBook Pro OS 10.11.6.
I compared the following two methods of writing file to response stream:
- Copying a fixed number of bytes from
FileChannel
toWritableByteChannel
usingtransferTo
- Reading a fixed number of bytes from
FileInputStream
into a byte array (size 4096) and writing toOutputStream
in a loop.
The time taken for a 5.2GB file is between 20 and 23 seconds with both methods. I tried transferTo
with the fixed number of bytes in single transfer set to following values: 4KB (i.e. 4 * 1024), 1MB and 50MB. The time taken to write is in the same range in all the 3 cases.
Time taken is measured from before entering the while-loop to after exiting the while-loop, in which bytes are read from the file. This is all on the server side. The network hop time does not figure into this.
Any ideas on what the reason could be? I am quite sure MacOS 10.11.6 should support zero-copy (i.e. sendfile
system call).
EDIT (6/18/2018):
I found the following blog post from 2015, saying that sendfile
on MacOS X is broken. Could it be that this problem still exists?
https://blog.phusion.nl/2015/06/04/the-brokenness-of-the-sendfile-system-call/