Enable TCP_NODELAY and SCTP_NODELAY by default

- Fixes #939
- Add PlatformDependent.canEnableTcpNoDelayByDefault()
  - Currently returns false on Android. Will change if necessary later.
This commit is contained in:
Trustin Lee 2013-01-31 12:17:09 +09:00
parent 152c969eab
commit 39357f3835
10 changed files with 66 additions and 18 deletions

View File

@ -42,6 +42,8 @@ public final class PlatformDependent {
private static final int JAVA_VERSION = javaVersion0();
private static final boolean CAN_ENABLE_TCP_NODELAY_BY_DEFAULT = !isAndroid();
private static final boolean HAS_UNSAFE = hasUnsafe0();
private static final boolean CAN_FREE_DIRECT_BUFFER = canFreeDirectBuffer0();
private static final boolean IS_UNALIGNED = isUnaligned0();
@ -75,6 +77,13 @@ public final class PlatformDependent {
return JAVA_VERSION;
}
/**
* Returns {@code true} if and only if it is fine to enable TCP_NODELAY socket option by default.
*/
public static boolean canEnableTcpNoDelayByDefault() {
return CAN_ENABLE_TCP_NODELAY_BY_DEFAULT;
}
/**
* Return {@code true} if {@code sun.misc.Unsafe} was found on the classpath and can be used.
*/

View File

@ -43,7 +43,6 @@ public class EchoServer {
b.group(new NioEventLoopGroup(), new NioEventLoopGroup())
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 100)
.childOption(ChannelOption.TCP_NODELAY, true)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override

View File

@ -53,7 +53,6 @@ public class FileServer {
b.group(new NioEventLoopGroup(), new NioEventLoopGroup())
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 100)
.childOption(ChannelOption.TCP_NODELAY, true)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override

View File

@ -20,7 +20,6 @@ import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.sctp.SctpChannel;
import io.netty.channel.sctp.SctpChannelOption;
import io.netty.channel.sctp.nio.NioSctpServerChannel;
import io.netty.channel.socket.nio.NioEventLoopGroup;
import io.netty.handler.logging.LogLevel;
@ -44,7 +43,6 @@ public class NioSctpEchoServer {
b.group(new NioEventLoopGroup(), new NioEventLoopGroup())
.channel(NioSctpServerChannel.class)
.option(ChannelOption.SO_BACKLOG, 100)
.childOption(SctpChannelOption.SCTP_NODELAY, true)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<SctpChannel>() {
@Override

View File

@ -20,7 +20,6 @@ import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.sctp.SctpChannel;
import io.netty.channel.sctp.SctpChannelOption;
import io.netty.channel.sctp.oio.OioSctpServerChannel;
import io.netty.channel.socket.oio.OioEventLoopGroup;
import io.netty.handler.logging.LogLevel;
@ -44,7 +43,6 @@ public class OioSctpEchoServer {
b.group(new OioEventLoopGroup(), new OioEventLoopGroup())
.channel(OioSctpServerChannel.class)
.option(ChannelOption.SO_BACKLOG, 100)
.childOption(SctpChannelOption.SCTP_NODELAY, true)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<SctpChannel>() {
@Override

View File

@ -22,6 +22,7 @@ import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelOption;
import io.netty.channel.DefaultChannelConfig;
import io.netty.util.internal.PlatformDependent;
import java.io.IOException;
import java.util.Map;
@ -41,6 +42,15 @@ public class DefaultSctpChannelConfig extends DefaultChannelConfig implements Sc
throw new NullPointerException("javaChannel");
}
this.javaChannel = javaChannel;
// Enable TCP_NODELAY by default if possible.
if (PlatformDependent.canEnableTcpNoDelayByDefault()) {
try {
setSctpNoDelay(true);
} catch (Exception e) {
// Ignore.
}
}
}
@Override

View File

@ -46,13 +46,17 @@ public interface SctpChannelConfig extends ChannelConfig {
/**
* Gets the <a href="http://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SCTP_NODELAY}</a> option.
* {@code SCTP_NODELAY}</a> option. Please note that the default value of this option is {@code true} unlike the
* operating system default ({@code false}). However, for some buggy platforms, such as Android, that shows erratic
* behavior with Nagle's algorithm disabled, the default value remains to be {@code false}.
*/
boolean isSctpNoDelay();
/**
* Sets the <a href="http://openjdk.java.net/projects/sctp/javadoc/com/sun/nio/sctp/SctpStandardSocketOption.html">
* {@code SCTP_NODELAY}</a> option.
* {@code SCTP_NODELAY}</a> option. Please note that the default value of this option is {@code true} unlike the
* operating system default ({@code false}). However, for some buggy platforms, such as Android, that shows erratic
* behavior with Nagle's algorithm disabled, the default value remains to be {@code false}.
*/
SctpChannelConfig setSctpNoDelay(boolean sctpNoDelay);

View File

@ -19,6 +19,7 @@ import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelOption;
import io.netty.channel.DefaultChannelConfig;
import io.netty.util.internal.PlatformDependent;
import java.net.Socket;
import java.net.SocketException;
@ -44,6 +45,15 @@ public class DefaultSocketChannelConfig extends DefaultChannelConfig
throw new NullPointerException("javaSocket");
}
this.javaSocket = javaSocket;
// Enable TCP_NODELAY by default if possible.
if (PlatformDependent.canEnableTcpNoDelayByDefault()) {
try {
setTcpNoDelay(true);
} catch (Exception e) {
// Ignore.
}
}
}
@Override

View File

@ -19,6 +19,7 @@ import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelConfig;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOption;
import java.net.Socket;
import java.net.StandardSocketOptions;
@ -35,33 +36,39 @@ import java.net.StandardSocketOptions;
* <tr>
* <th>Name</th><th>Associated setter method</th>
* </tr><tr>
* <td>{@link io.netty.channel.ChannelOption#SO_KEEPALIVE}</td><td>{@link #setKeepAlive(boolean)}</td>
* <td>{@link ChannelOption#SO_KEEPALIVE}</td><td>{@link #setKeepAlive(boolean)}</td>
* </tr><tr>
* <td>{@link io.netty.channel.ChannelOption#SO_REUSEADDR}</td><td>{@link #setReuseAddress(boolean)}</td>
* <td>{@link ChannelOption#SO_REUSEADDR}</td><td>{@link #setReuseAddress(boolean)}</td>
* </tr><tr>
* <td>{@link io.netty.channel.ChannelOption#SO_LINGER}</td><td>{@link #setSoLinger(int)}</td>
* <td>{@link ChannelOption#SO_LINGER}</td><td>{@link #setSoLinger(int)}</td>
* </tr><tr>
* <td>{@link io.netty.channel.ChannelOption#TCP_NODELAY}</td><td>{@link #setTcpNoDelay(boolean)}</td>
* <td>{@link ChannelOption#TCP_NODELAY}</td><td>{@link #setTcpNoDelay(boolean)}</td>
* </tr><tr>
* <td>{@link io.netty.channel.ChannelOption#SO_RCVBUF}</td><td>{@link #setReceiveBufferSize(int)}</td>
* <td>{@link ChannelOption#SO_RCVBUF}</td><td>{@link #setReceiveBufferSize(int)}</td>
* </tr><tr>
* <td>{@link io.netty.channel.ChannelOption#SO_SNDBUF}</td><td>{@link #setSendBufferSize(int)}</td>
* <td>{@link ChannelOption#SO_SNDBUF}</td><td>{@link #setSendBufferSize(int)}</td>
* </tr><tr>
* <td>{@link io.netty.channel.ChannelOption#IP_TOS}</td><td>{@link #setTrafficClass(int)}</td>
* <td>{@link ChannelOption#IP_TOS}</td><td>{@link #setTrafficClass(int)}</td>
* </tr><tr>
* <td>{@link io.netty.channel.ChannelOption#ALLOW_HALF_CLOSURE}</td><td>{@link #setAllowHalfClosure(boolean)}</td>
* <td>{@link ChannelOption#ALLOW_HALF_CLOSURE}</td><td>{@link #setAllowHalfClosure(boolean)}</td>
* </tr>
* </table>
*/
public interface SocketChannelConfig extends ChannelConfig {
/**
* Gets the {@link StandardSocketOptions#TCP_NODELAY} option.
* Gets the {@link StandardSocketOptions#TCP_NODELAY} option. Please note that the default value of this option
* is {@code true} unlike the operating system default ({@code false}). However, for some buggy platforms, such as
* Android, that shows erratic behavior with Nagle's algorithm disabled, the default value remains to be
* {@code false}.
*/
boolean isTcpNoDelay();
/**
* Sets the {@link StandardSocketOptions#TCP_NODELAY} option.
* Sets the {@link StandardSocketOptions#TCP_NODELAY} option. Please note that the default value of this option
* is {@code true} unlike the operating system default ({@code false}). However, for some buggy platforms, such as
* Android, that shows erratic behavior with Nagle's algorithm disabled, the default value remains to be
* {@code false}.
*/
SocketChannelConfig setTcpNoDelay(boolean tcpNoDelay);

View File

@ -19,6 +19,7 @@ import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelOption;
import io.netty.channel.DefaultChannelConfig;
import io.netty.util.internal.PlatformDependent;
import java.io.IOException;
import java.net.SocketOption;
@ -57,6 +58,7 @@ final class DefaultAioSocketChannelConfig extends DefaultChannelConfig
*/
DefaultAioSocketChannelConfig(AioSocketChannel channel) {
super(channel);
enableTcpNoDelay();
}
/**
@ -65,6 +67,18 @@ final class DefaultAioSocketChannelConfig extends DefaultChannelConfig
DefaultAioSocketChannelConfig(AioSocketChannel channel, NetworkChannel javaChannel) {
super(channel);
this.javaChannel.set(javaChannel);
enableTcpNoDelay();
}
private void enableTcpNoDelay() {
// Enable TCP_NODELAY by default if possible.
if (PlatformDependent.canEnableTcpNoDelayByDefault()) {
try {
setTcpNoDelay(true);
} catch (Exception e) {
// Ignore.
}
}
}
@Override