Callback Based Selectors
Alan.Bateman at oracle.com
Wed Mar 14 14:05:58 UTC 2018
On 16/01/2016 11:14, Richard Warburton wrote:
> Hi gents,
> I've prototyped a callback based addition to the NIO Selector, which
> I've previously talked through a bit with Alan Bateman. The goal of
> the callback based selector is to avoid the current pattern of calling
> select/selectNow on a Nio selector and then having to iterate over a
> hashmap produced. This pattern being quite object allocation heavy for
> a critical path and also involving obtaining and releasing multiple
> locks. I'd like to propose that the following patch, which adds the
> ability to perform a select on a Selector that takes a callback handler.
> I'm happy to iterate on the patch a bit based upon people's feedback
> and discuss any potential concerns or issues that you may have with
> the patch. Looking forward to hearing your feedback.
This one has been on my list for a long time to study more closely. When
we discussed it here in 2016 I had concerns about invoking a consumer
while synchronized on the selector and other locks. It has grown on my a
bit so I spent a bit of time recently to work through the implications,
both spec and implementation.
For the spec: The Selector API describes selection operations in its
class description and it's important to keep that consistent when
introducing a new way to be notified of channels ready for I/O operations.
The action is arbitrary code and we have to assume it will behave as if
it's a bull in a china shop. It might attempt another selection
operation on the same selector, it might close the selector, it might
change the interest set or cancel a key for a channel registered with
the selector but not yet seen by the consumer. All of these scenarios
Locking was mostly ignored in the original prototype but the locking has
to be consistent with how the existing selection operations are
specified. The main reason is processing the cancelled-key set means
removing keys from the key set and selected-key set. On the surface, the
new methods should not care about the selected-key set but they have to
maintain the invariant that the selected-key set is always a subset of
the selector's key set.
Another point of detail is that the action may need to be called more
than once for the same key but different ready sets. We have this with
the kqueue implementation where events for read and write are registered
with different filters. Other implementation might maintain separate
poll arrays for read and write events.
In terms of performance, the main benefit is that avoids adding keys to
the selected-key set, only to be removed almost immediately by the code
doing the select. This avoids garbage so helps the GC too. If we go
ahead with these methods then it's important to get a good range of
performance data and also see whether a specialized set to support the
usage pattern of the selected-key set might be alternative to
introducing new APIs.
I've put a webrev here with candidate changes to the Selector API. It's
one select(Consumer<SelectionKey>, timeout) for now, the
select(Consumer<SelectionKey>) and selectNow(Consumer<SelectionKey>)
variants are easy to add if needed. The webrev has a default
implementation based on the existing API, and then implementations for
macOS and Linux. Other platforms could be added later of course. I've
also included a test that covers most of the scenarios.
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the nio-dev