-
Notifications
You must be signed in to change notification settings - Fork 5.8k
8253478: (se) epoll Selector should use eventfd for wakeup instead of pipe #2082
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 |
Webrevs
|
@bplb I think it's too premature to ask us to review this until you have some performance data. Do we have any existing micros for wakeup? |
Yes. I have one based on the Wakeup test but it is rather ugly. |
This simple benchmark below gives results for the
|
I did experiments with eventfd(2) a few years ago but didn't see any difference at the time. I think it would be useful to include the PR the results from the JMH runs so that there is at least some record of the results. As regards the patch, I would have expected the only native code is be the method that creates the eventfd instance. The set/reset methods can be implemented with IOUtil.write1/drain1. Also I think the EventFD constructor needs a flag so decide the blocking mode, alternative we ignore it and using the existing IOUtil.configureBlocking. |
Mailing list message from Brian Burkhalter on nio-dev:
I?ll do that.
Reading or writing fewer than 8 bytes from / to the eventfd object will result in an EINVAL error. Yes, IOUtil.drain(int) could be used instead of EventFD.reset(), although its more complex, but there is no write() in IOUtil which does not require a FileDescriptor and a ByteBuffer, which seems like overkill here. A method IOUtil.write(int fd, long value) could be added however.
Or maybe better yet just go with hard-coded blocking or non-blocking and dispense with the parameter. Brian |
…ventFD using IOUtil methods.
Benchmark output for commit 3:
|
Throughput improvement as measured by the benchmark looks to be a bit over 3% for eventfd wakeup with respect to pipe wakeup. The confidence intervals of the pipe wakeup results mostly do not overlap those of the corresponding eventfd wakeup results which tends to suggest some degree of reliability. Summary of benchmark results:
|
Are you going to include the micro benchmark in the patch? The presentation of the summary in the comments is hard to read but a 3% is okay. It was inconclusive when I tried a long time ago. The updated patch looks better. IOUtil.write(fd, long) begs the question as to whether the 8 bytes for the long are written in big or little endian. I realise it doesn't matter for EventFD but we will need to get this right. I would be tempted to call evetnfd with the flags set to 0 and then use IOUtil.configureBlocking when we need it non-blocking. |
… reinstate EventFD.set0(), use IOUtil.configureBlocking().
Updated the patch to:
|
long fds = IOUtil.makePipe(false); | ||
this.fd0 = (int) (fds >>> 32); | ||
this.fd1 = (int) fds; | ||
this.eventfd = new EventFD(); | ||
} catch (IOException ioe) { | ||
EPoll.freePollArray(pollArrayAddress); | ||
FileDispatcherImpl.closeIntFD(epfd); | ||
throw ioe; | ||
} | ||
|
||
// register one end of the socket pair for wakeups |
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 guess the comment at line 89 no longer applies.
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.
You are correct, thanks.
FileDispatcherImpl.closeIntFD(efd); | ||
} | ||
|
||
static native int eventfd0() throws IOException; |
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 assume the native methods should be private.
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.
So changed.
*/ | ||
EventFD() throws IOException { | ||
efd = eventfd0(); | ||
IOUtil.configureBlocking(IOUtil.newFD(efd), false); |
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.
If there is just one no-arg constructor then I think it should create the eventfd with the default settings, meaning blocking mode. A second constructor that takes a boolean blocking parameter would be okay too.
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.
Above suggestions addressed.
* @param the integral eventfd file descriptor | ||
* @return the number of bytes written; should equal 8 | ||
*/ | ||
static private native int set0(int efd) throws IOException; |
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.
Minor nit but we usually put the private modifier first.
*/ | ||
EventFD(boolean blocking) throws IOException { | ||
efd = eventfd0(); | ||
IOUtil.configureBlocking(IOUtil.newFD(efd), blocking); |
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.
This looks okay but the addition of the blocking parameter means you can go back to one of the early iterations and just calling eventfd with the EFD_NONBLOCK. Up to you.
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 am not sure I understand this comment as a previous comment preferred IOUtil.configureBlocking()
to set the blocking state.
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.
The previous comments were in the context of the no-arg EventFD constructor where we expected it would be created in blocking mode. In that context EPollSelectorImpl would use IOUtil.configureBlocking to configure it to non-blocking. In the new version, there is a blocking parameter so EventFD can use IOUtil.configureBlocking when blocking is "false", or specify EFD_NONBLOCK to eventfd, either is okay with me.
@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 145 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 |
/integrate |
@bplb Since your change was applied there have been 145 commits pushed to the
Your commit was automatically rebased without conflicts. Pushed as commit a8073ef. 💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored. |
Please review this change which modifies the Linux
epoll(7)
-basedSelector
to useeventfd(2)
instead ofpipe(2)
in its wakeup mechanism. The change passes all tier 1-tier 3 tests on Linux. Based on rudimentary testing, there does not appear to be any appreciable change in performance. One improvement however is that only one file descriptor instead of two is used for the wakeup. No test is included as the code is covered well by existing tests.Progress
Issue
Reviewers
Download
$ git fetch https://git.openjdk.java.net/jdk pull/2082/head:pull/2082
$ git checkout pull/2082