RFR: 8265175: (fs) Files.copy(Path, Path, CopyOption...) should use sendfile on Linux [v3]

Alan Bateman alanb at openjdk.java.net
Thu Apr 15 11:12:35 UTC 2021


On Wed, 14 Apr 2021 23:47:57 GMT, Brian Burkhalter <bpb at openjdk.org> wrote:

>> Please consider this request to change the underlying native implementation of `java.nio.file.Files.copy(Path,Path,CopyOption...)` on Linux only to perform zero-copy via `sendfile(2)`. The `sendfile()` system call is already used in `java.nio.channels.FIleChannel.transferTo​(long,long,WritableByteChannel)`. It is intentionally _not_ proposed to use `sendfile()` in the native macOS implementation as on macOS the function requires that the destination file descriptor is for a socket.
>> 
>> This change showed some performance improvement as measured by JMH.
>> 
>> **Before: user-space buffers (read() + write())**
>> 
>> Benchmark           (size)   Mode  Cnt      Score     Error  Units
>> FilesCopy.copy       10240  thrpt    5  39167.400 ± 683.887  ops/s
>> FilesCopy.copy       51200  thrpt    5  20782.622 ± 558.031  ops/s
>> FilesCopy.copy      102400  thrpt    5  13260.709 ± 176.673  ops/s
>> FilesCopy.copy      512000  thrpt    5   3171.837 ± 175.803  ops/s
>> FilesCopy.copy     1048568  thrpt    5   1654.253 ±  39.419  ops/s
>> FilesCopy.copy    10485760  thrpt    5    145.328 ±   7.192  ops/s
>> FilesCopy.copy   104857600  thrpt    5     12.440 ±   2.275  ops/s
>> FilesCopy.copy  1073741824  thrpt    5      1.073 ±   0.081  ops/s
>> 
>> **After: zero-copy (sendfile())**
>> 
>> Benchmark           (size)   Mode  Cnt      Score     Error  Units
>> FilesCopy.copy       10240  thrpt    5  40571.516 ± 548.977  ops/s
>> FilesCopy.copy       51200  thrpt    5  23993.334 ± 506.817  ops/s
>> FilesCopy.copy      102400  thrpt    5  15927.485 ± 309.081  ops/s
>> FilesCopy.copy      512000  thrpt    5   4207.129 ±  95.454  ops/s
>> FilesCopy.copy     1048568  thrpt    5   2147.046 ±  33.446  ops/s
>> FilesCopy.copy    10485760  thrpt    5    148.798 ±   1.329  ops/s
>> FilesCopy.copy   104857600  thrpt    5     14.541 ±   0.675  ops/s
>> FilesCopy.copy  1073741824  thrpt    5      1.270 ±   0.029  ops/s
>
> Brian Burkhalter has updated the pull request incrementally with three additional commits since the last revision:
> 
>  - Merge
>  - 8265175: Delete fstat() calls, read to EOF, change sendfile() to sendfile64(), handle EINTR case
>  - 8265175: (fs) Files.copy(Path,Path,CopyOption...) should use sendfile on Linux

src/java.base/unix/native/libnio/fs/UnixCopyFile.c line 79:

> 77:         return;
> 78:     }
> 79: #endif

This version looks much better but it missing the error checking. If bytes_sent is -1 then we should throw UnixException with the errno like the existing code.

What would you think about setting count to 1MB or 4MB so that there is at least some chance for cancellation when the file is huge.

Given that the new implementation will call sendfile64 until EOF then there is no reason to fall through to the old implementation, the old implementation goes into the #else ...

-------------

PR: https://git.openjdk.java.net/jdk/pull/3476


More information about the nio-dev mailing list