RFR: 6980847: (fs) Files.copy needs to be tuned [v3]
Brian Burkhalter
bpb at openjdk.java.net
Thu Jun 16 01:40:03 UTC 2022
On Wed, 15 Jun 2022 17:52:13 GMT, Brian Burkhalter <bpb at openjdk.org> wrote:
>> Modify `UnixCopyFile.copyFile()` to set the transfer size to the least common multiple of the source and destination file block sizes if the block sizes are not equal. Modify `WindowsFileCopy.copy()` to set `COPY_FILE_NO_BUFFERING` in the flags passed to `CopyFileEx()` if the size of the transfer is greater than a threshold.
>
> Brian Burkhalter has updated the pull request incrementally with one additional commit since the last revision:
>
> 6980847: Remove unnecessary catch of SecurityException and UnsupportedOperationException which are not thrown by blockSize()
Responding to [Bernd's comments](https://mail.openjdk.org/pipermail/nio-dev/2022-June/011466.html).
It has been observed before that a larger buffer can increase throughput so increasing the minimum transfer size here seems reasonable. I don’t think it would be bad to increase it to 16K. Perhaps do something like the following where `TRANSFER_SIZE` is 16384 instead of 8192
if (transferSize < TRANSFER_SIZE) {
int factor = (int)((TRANSFER_SIZE + transferSize - 1)/transferSize);
transferSize *= factor;
}
which will probably always compute 16384.
I think that
int advice = POSIX_FADV_SEQUENTIAL | POSIX_FADV_NOREUSE | POSIX_FADV_WILLNEED;
posix_fadvise(src, 0, 0, advice);
is a good idea.
Several mentions online state that `st_blksize` for an NFS server is the page size, but local testing shows it to be the block size of the mounted disk.
Not much benchmark work was done on this topic except on Windows which was to determine the no-buffering threshold. I went back and generated some numbers today. `patch1` is as of the third commit, `patch2` as of the fourth which I will push shortly.
==> ../master.txt <==
Benchmark (length) Mode Cnt Score Error Units
CopyFile.copy 10000 thrpt 10 32685.396 ± 1623.472 ops/s
CopyFile.copy 100000 thrpt 10 11660.298 ± 156.204 ops/s
CopyFile.copy 1000000 thrpt 10 1504.661 ± 15.264 ops/s
CopyFile.copy 10000000 thrpt 10 118.880 ± 5.999 ops/s
==> ../patch1.txt <==
Benchmark (length) Mode Cnt Score Error Units
CopyFile.copy 10000 thrpt 10 30343.618 ± 955.469 ops/s
CopyFile.copy 100000 thrpt 10 11295.039 ± 102.986 ops/s
CopyFile.copy 1000000 thrpt 10 1490.852 ± 19.018 ops/s
CopyFile.copy 10000000 thrpt 10 111.626 ± 2.392 ops/s
==> ../patch2-no-fadvise.txt <==
Benchmark (length) Mode Cnt Score Error Units
CopyFile.copy 10000 thrpt 10 31743.019 ± 974.794 ops/s
CopyFile.copy 100000 thrpt 10 12295.192 ± 187.331 ops/s
CopyFile.copy 1000000 thrpt 10 1656.561 ± 23.102 ops/s
CopyFile.copy 10000000 thrpt 10 122.700 ± 1.783 ops/s
==> ../patch2.txt <==
Benchmark (length) Mode Cnt Score Error Units
CopyFile.copy 10000 thrpt 10 31735.385 ± 374.000 ops/s
CopyFile.copy 100000 thrpt 10 12049.334 ± 112.960 ops/s
CopyFile.copy 1000000 thrpt 10 1664.070 ± 33.637 ops/s
CopyFile.copy 10000000 thrpt 10 121.623 ± 1.258 ops/s
It looks like having the minimum transfer size be 16384 is helpful; `fadvise()` does not do much here.
Please note that the transfer by read-write loop is rather an edge case: it is never used on macOS, and on Linux only if sendfile() fails. It is however the only code path on other Unix variants.
-------------
PR: https://git.openjdk.org/jdk/pull/9161
More information about the nio-dev
mailing list