-
Notifications
You must be signed in to change notification settings - Fork 5.8k
8274112: (fc) Tune FileChannel.transferTo() #5623
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
Conversation
👋 Welcome back bpb! A progress list of the required criteria for merging this PR into |
On Linux, On macOS, native read-write was measured to be faster than both the trusted and
and the proposed native read-write path
On Windows the native read-write path was also measured to be faster than the trusted path except that beyond a certain limit the trusted path becomes faster than native read-write. The value of this limit appears to be approximately 2MB but more verification might be needed. |
Webrevs
|
No objection to try to improve the macOS and Windows cases but I'm concerned about the maintainability. It might be that we have to do some significant refactoring of the FileChannel implementation to support these cases. I think the native methods should be as simple as possible and all the decisions on the dispatching should be in the Java code, not the native code. |
I had considered adding a fourth path, |
transferToDirectly already tests if the target is a FileChannel so I think a transferToFileChannel would be cleaner. My main concern is that there is many cases and have some in FCI and some in the native code makes it difficult to maintain. I'd prefer to have the native methods be simple "leaf" methods and all decisions are done in the FCI code. |
I agree about keeping the decisions at the Java level. I will work on refactoring this. |
The second commit refactored
the |
Thanks for the updates, this looks much cleaner and maintainable now. Busy just now so will look at it closer later. |
Are you planning to update the PR with the changes that we discussed here? |
The latest version looks okay but I'm wondering if we can move transfer_read_write out of the native code. As you know, in this area we try to have the JNI methods do a single syscall. With this change we've put a transfer loop into the native code when it should probably be in Java. |
I believe that prior to publishing this PR I tested the case of doing the read-write transfer in Java and it did not afford the same sort of performance improvement as what is proposed here. This version was inspired more by the native code underlying the Unix implementation of Files.copy() (UnixCopyFile.c) which has exactly the same sort of native read-write loop in it. The question here then becomes whether the performance improvement is worth the extra native code. |
@bplb This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply add a new comment to the pull request. Feel free to ask for assistance if you need help with progressing this pull request towards integration! |
continue ... |
@bplb This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply add a new comment to the pull request. Feel free to ask for assistance if you need help with progressing this pull request towards integration! |
continue |
@bplb This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply add a new comment to the pull request. Feel free to ask for assistance if you need help with progressing this pull request towards integration! |
continue ... |
@bplb This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply add a new comment to the pull request. Feel free to ask for assistance if you need help with progressing this pull request towards integration! |
@bplb This pull request has been inactive for more than 8 weeks and will now be automatically closed. If you would like to continue working on this pull request in the future, feel free to reopen it! This can be done using the |
/open |
@bplb This pull request is now open |
…; use Linux copy_file_range() for direct copy if available
Commit 65e3adc makes the following changes:
The effects of these changes are:
|
As discussed in JDK-8282039, using |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you've got this to a good place and much simpler than the early iterations. So I think the src changes are good. I don't have time right now to do a detailed review of the test, maybe @LanceAndersen might be help on that.
@bplb This change now passes all automated pre-integration checks. ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details. After integration, the commit message for the final commit will be:
You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed. At the time when this comment was updated there had been 57 new commits pushed to the
As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details. ➡️ To integrate this PR with the above commit message to the |
rand.nextBytes(expected); | ||
for (int i=0; i<size; i++) | ||
if (incoming[i] != expected[i]) | ||
throw new RuntimeException("Data corrupted"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps if (!Arrays.equals(incoming, 0, size, expected, 0, size))...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree but I would take it further and create a utility method so that it is reusable as it looks like you could take advantage of it later in the test(around line 175)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps
if (!Arrays.equals(incoming, 0, size, expected, 0, size))...
I think here the simpler Arrays.equals(byte[],byte[])
can be used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree but I would take it further and create a utility method so that it is reusable as it looks like you could take advantage of it later in the test(around line 175)
I think that if line 124 and after uses the simpler Arrays.equals(byte[],byte[])
then such a utility method would be less useful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed by commit c72b4b5.
static void generateBigFile(File file) throws Exception { | ||
private static void transferFileDirectly() throws Exception { | ||
outFile.delete(); | ||
FileOutputStream fos = new FileOutputStream(outFile); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can try-with-resources be used here for both fos and out?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. Fixed by commit c72b4b5.
if (bytesTransferred >= 0) | ||
pos += bytesTransferred; | ||
else | ||
throw new Exception("transfer failed"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Including some position information in the exception would help diagnose, especially with intermittent failures, if they happen.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed by commit c72b4b5.
I would probably have been tempted to convert this test to leverage TestNG as I think it would streamline the test a bit (or safe this for a future date)
I prefer to leave the TestNG conversion to another issue TBD.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some minor comments.
I would probably have been tempted to convert this test to leverage TestNG as I think it would streamline the test a bit (or safe this for a future date)
static int CHUNK_SIZE = 1024 * 9; | ||
private static final Random RAND = RandomFactory.getRandom(); | ||
|
||
private static final int FILE_SIZE = 1000*1024; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could use a comment regarding the reason the file size is what it is
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't recall why that particular value was chosen except in relation to other constants. Will add some comments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed by commit c72b4b5.
rand.nextBytes(expected); | ||
for (int i=0; i<size; i++) | ||
if (incoming[i] != expected[i]) | ||
throw new RuntimeException("Data corrupted"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree but I would take it further and create a utility method so that it is reusable as it looks like you could take advantage of it later in the test(around line 175)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good.
/integrate |
Going to push as commit 17cc713.
Your commit was automatically rebased without conflicts. |
Please consider this patch which would improve the performance of
FileChannel.transferTo()
on macOS and Windows.Progress
Issue
Reviewers
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.java.net/jdk pull/5623/head:pull/5623
$ git checkout pull/5623
Update a local copy of the PR:
$ git checkout pull/5623
$ git pull https://git.openjdk.java.net/jdk pull/5623/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 5623
View PR using the GUI difftool:
$ git pr show -t 5623
Using diff file
Download this PR as a diff file:
https://git.openjdk.java.net/jdk/pull/5623.diff