RFR: 8264744: (fc, fs) Support file cloning in Unix versions of FileChannel transfer and Files copy methods
Brian Burkhalter
bpb at openjdk.org
Thu Jul 14 17:23:44 UTC 2022
On Wed, 13 Jul 2022 23:25:00 GMT, Brian Burkhalter <bpb at openjdk.org> wrote:
> Add file cloning to `java.nio.channels.FileChannel::transferTo` and `java.nio.file.Files.copy(Path,Path)`.
On Linux, the `copy_file_range(2)` system call already includes file cloning if available, so there is no need to add an explicit call to `ioctl(2)` with request code `FICLONE` or `FICLONERANGE` unless `copy_file_range()` is unavailable. Therefore the Linux `ioctl_ficlone` branch in `cloneFile0()` is conditional, and an invocation of `copy_file_range()` is prepended in `directCopy0()` on Linux. Note that as `FileChannel::transferFrom` was already calling `copy_file_range()`, it was already using cloning on Linux when possible.
On macOS, the available cloning system calls are `clonefile(2)` and `copyfile(3)` with for the latter `COPYFILE_CLONE` set in `flags`. There is no cloning call which accepts file descriptors as the target cannot already exist when the system call is invoked. There is also no call on macOS to clone a range of a file, hence there is no cloning added for `transferFrom()` nor `transferTo()` on macOS.
The througput of `Files::copy` is greatly increased by using cloning, at the expense of course of the first subsequent write to the target path being slower due to copy-on-write (CoW).
throughput (ops/s)
APFS (macOS) BTRFS (Linux) EXT4 (Linux)
count before after before after before after
10240 1578.971 2902.128 24331.624 31074.073 27722.815 27574.891
51200 1849.027 2917.996 19295.797 31313.13 18590.463 18650.098
102400 1757.527 2899.018 15874.133 31243.225 13242.939 13235.246
512000 1195.215 2818.547 5856.964 30972.607 3998.696 3903.092
1048568 829.433 2169.738 3283.841 31097.633 2056.693 2014.939
10485760 126.736 2336.032 236.58 30754.849 154.103 153.356
104857600 15.014 2361.208 22.352 31123.14 14.864 14.746
1073741824 2.484 2335.799 1.549 30682.197 1.408 1.41
The throughput within a CoW file system (APFS and BTRFS) is much higher, especially for large files, and that within a non-CoW file system (EXT4) is effectively unchanged.
As APFS supports CoW, existing tests should cover these changes. For Linux, a dynamic search for file systems supporting CoW is added in the `CopyAndMove` test.
It is unclear whether the Linux branch in `cloneFile0` should attempt to use `ioctl_ficlone` if `copy_file_range` is undefined, as currently proposed, or simply always return `IOS_UNAVAILABLE`. It is likewise unclear whether `ioctl_ficlonerange` should be used in `transferFrom0` and `transferTo0` if `copy_file_range` is undefined (it currently is not).
In the initial version of this patch, cloning is enabled by default. In the issue description the possibility of adding a (JDK-specific?) `CopyOption` or system property to disable cloning was mentioned. There is also the opposite approach of cloning being disabled by default, with a `CopyOption` or system property required to enable it.
-------------
PR: https://git.openjdk.org/jdk/pull/9486
More information about the nio-dev
mailing list