From e0b2f34a379777a7d4e1c9efe31a1d1c66bb6d74 Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Thu, 13 Mar 2014 06:46:05 +0100 Subject: [PATCH] [#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. --- pom.xml | 1 + .../netty/channel/socket/nio/NioDatagramChannel.java | 12 ++++++++++-- .../channel/socket/nio/NioServerSocketChannel.java | 10 +++++++++- .../netty/channel/socket/nio/NioSocketChannel.java | 10 +++++++++- 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 432d7542a0..dc4bc432d5 100644 --- a/pom.xml +++ b/pom.xml @@ -432,6 +432,7 @@ java.nio.channels.DatagramChannel java.nio.channels.MembershipKey java.net.StandardProtocolFamily + java.nio.channels.spi.SelectorProvider java.nio.channels.AsynchronousChannel diff --git a/transport/src/main/java/io/netty/channel/socket/nio/NioDatagramChannel.java b/transport/src/main/java/io/netty/channel/socket/nio/NioDatagramChannel.java index c2619aba88..0c4259db04 100644 --- a/transport/src/main/java/io/netty/channel/socket/nio/NioDatagramChannel.java +++ b/transport/src/main/java/io/netty/channel/socket/nio/NioDatagramChannel.java @@ -45,6 +45,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; @@ -62,6 +63,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> memberships = @@ -71,7 +73,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 #2308. + */ + return SELECTOR_PROVIDER.openDatagramChannel(); } catch (IOException e) { throw new ChannelException("Failed to open a socket.", e); } @@ -85,7 +93,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); } diff --git a/transport/src/main/java/io/netty/channel/socket/nio/NioServerSocketChannel.java b/transport/src/main/java/io/netty/channel/socket/nio/NioServerSocketChannel.java index e294f52b5d..fc04d7a99b 100644 --- a/transport/src/main/java/io/netty/channel/socket/nio/NioServerSocketChannel.java +++ b/transport/src/main/java/io/netty/channel/socket/nio/NioServerSocketChannel.java @@ -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 #2308. + */ + return SELECTOR_PROVIDER.openServerSocketChannel(); } catch (IOException e) { throw new ChannelException( "Failed to open a server socket.", e); diff --git a/transport/src/main/java/io/netty/channel/socket/nio/NioSocketChannel.java b/transport/src/main/java/io/netty/channel/socket/nio/NioSocketChannel.java index 241666f6d6..1690c28d60 100644 --- a/transport/src/main/java/io/netty/channel/socket/nio/NioSocketChannel.java +++ b/transport/src/main/java/io/netty/channel/socket/nio/NioSocketChannel.java @@ -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 #2308. + */ + return SELECTOR_PROVIDER.openSocketChannel(); } catch (IOException e) { throw new ChannelException("Failed to open a socket.", e); }