[#2308] Use SelectorProvider.open*() to open NIO channels and so remove condition when create new NIO channels.

Motivation:
At the moment we use SocketChannel.open(), ServerSocketChannel.open() and DatagramSocketChannel.open(...) within the constructor of our
NIO channels. This introduces a bottleneck if you create a lot of connections as these calls delegate to SelectorProvider.provider() which
uses synchronized internal. This change removed the bottleneck.

Modifications:
Obtain a static instance of the SelectorProvider and use SelectorProvider.openSocketChannel(), SelectorProvider.openServerSocketChannel() and
SelectorProvider.openDatagramChannel(). This eliminates the bottleneck as SelectorProvider.provider() is not called on every channel creation.

Result:
Less conditions when create new channels.
This commit is contained in:
Norman Maurer 2014-03-13 06:46:05 +01:00
parent 50e95383a3
commit 69d3cf5539
4 changed files with 29 additions and 4 deletions

View File

@ -433,6 +433,7 @@
<ignore>java.nio.channels.DatagramChannel</ignore>
<ignore>java.nio.channels.MembershipKey</ignore>
<ignore>java.net.StandardProtocolFamily</ignore>
<ignore>java.nio.channels.spi.SelectorProvider</ignore>
<!-- Used for NIO. 2 -->
<ignore>java.nio.channels.AsynchronousChannel</ignore>

View File

@ -43,6 +43,7 @@ import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.nio.channels.MembershipKey;
import java.nio.channels.SelectionKey;
import java.nio.channels.spi.SelectorProvider;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
@ -60,6 +61,7 @@ public final class NioDatagramChannel
extends AbstractNioMessageChannel implements io.netty.channel.socket.DatagramChannel {
private static final ChannelMetadata METADATA = new ChannelMetadata(true);
private static final SelectorProvider SELECTOR_PROVIDER = SelectorProvider.provider();
private final DatagramChannelConfig config;
private final Map<InetAddress, List<MembershipKey>> memberships =
@ -69,7 +71,13 @@ public final class NioDatagramChannel
private static DatagramChannel newSocket() {
try {
return DatagramChannel.open();
/**
* Use the {@link SelectorProvider} to open {@link SocketChannel} and so remove condition in
* {@link SelectorProvider#provider()} which is called by each DatagramChannel.open() otherwise.
*
* See <a href="See https://github.com/netty/netty/issues/2308">#2308</a>.
*/
return SELECTOR_PROVIDER.openDatagramChannel();
} catch (IOException e) {
throw new ChannelException("Failed to open a socket.", e);
}
@ -83,7 +91,7 @@ public final class NioDatagramChannel
checkJavaVersion();
try {
return DatagramChannel.open(ProtocolFamilyConverter.convert(ipFamily));
return SELECTOR_PROVIDER.openDatagramChannel(ProtocolFamilyConverter.convert(ipFamily));
} catch (IOException e) {
throw new ChannelException("Failed to open a socket.", e);
}

View File

@ -30,6 +30,7 @@ import java.net.SocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.SelectorProvider;
import java.util.List;
/**
@ -40,12 +41,19 @@ public class NioServerSocketChannel extends AbstractNioMessageChannel
implements io.netty.channel.socket.ServerSocketChannel {
private static final ChannelMetadata METADATA = new ChannelMetadata(false);
private static final SelectorProvider SELECTOR_PROVIDER = SelectorProvider.provider();
private static final InternalLogger logger = InternalLoggerFactory.getInstance(NioServerSocketChannel.class);
private static ServerSocketChannel newSocket() {
try {
return ServerSocketChannel.open();
/**
* Use the {@link SelectorProvider} to open {@link SocketChannel} and so remove condition in
* {@link SelectorProvider#provider()} which is called by each ServerSocketChannel.open() otherwise.
*
* See <a href="See https://github.com/netty/netty/issues/2308">#2308</a>.
*/
return SELECTOR_PROVIDER.openServerSocketChannel();
} catch (IOException e) {
throw new ChannelException(
"Failed to open a server socket.", e);

View File

@ -36,6 +36,7 @@ import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.SelectorProvider;
/**
* {@link io.netty.channel.socket.SocketChannel} which uses NIO selector based implementation.
@ -43,10 +44,17 @@ import java.nio.channels.SocketChannel;
public class NioSocketChannel extends AbstractNioByteChannel implements io.netty.channel.socket.SocketChannel {
private static final ChannelMetadata METADATA = new ChannelMetadata(false);
private static final SelectorProvider SELECTOR_PROVIDER = SelectorProvider.provider();
private static SocketChannel newSocket() {
try {
return SocketChannel.open();
/**
* Use the {@link SelectorProvider} to open {@link SocketChannel} and so remove condition in
* {@link SelectorProvider#provider()} which is called by each SocketChannel.open() otherwise.
*
* See <a href="See https://github.com/netty/netty/issues/2308">#2308</a>.
*/
return SELECTOR_PROVIDER.openSocketChannel();
} catch (IOException e) {
throw new ChannelException("Failed to open a socket.", e);
}