Allow to configure socket option SO_BUSY_POLL (#8268)
Motivation: When using Epoll based transport, allow applications to configure SO_BUSY_POLL socket option: SO_BUSY_POLL (since Linux 3.11) Sets the approximate time in microseconds to busy poll on a blocking receive when there is no data. Increasing this value requires CAP_NET_ADMIN. The default for this option is con‐ trolled by the /proc/sys/net/core/busy_read file. The value in the /proc/sys/net/core/busy_poll file determines how long select(2) and poll(2) will busy poll when they oper‐ ate on sockets with SO_BUSY_POLL set and no events to report are found. In both cases, busy polling will only be done when the socket last received data from a network device that supports this option. While busy polling may improve latency of some applications, care must be taken when using it since this will increase both CPU utilization and power usage. Modification: Added SO_BUSY_POLL socket option Result: Able to configure SO_BUSY_POLL from Netty
This commit is contained in:
parent
c14efd952d
commit
2a1596a4e9
@ -50,6 +50,11 @@
|
||||
#define TCP_NOTSENT_LOWAT 25
|
||||
#endif
|
||||
|
||||
// SO_BUSY_POLL is defined in linux 3.11. We define this here so older kernels can compile.
|
||||
#ifndef SO_BUSY_POLL
|
||||
#define SO_BUSY_POLL 46
|
||||
#endif
|
||||
|
||||
static jclass peerCredentialsClass = NULL;
|
||||
static jmethodID peerCredentialsMethodId = NULL;
|
||||
|
||||
@ -111,6 +116,10 @@ static void netty_epoll_linuxsocket_setIpRecvOrigDestAddr(JNIEnv* env, jclass cl
|
||||
netty_unix_socket_setOption(env, fd, IPPROTO_IP, IP_RECVORIGDSTADDR, &optval, sizeof(optval));
|
||||
}
|
||||
|
||||
static void netty_epoll_linuxsocket_setSoBusyPoll(JNIEnv* env, jclass clazz, jint fd, jint optval) {
|
||||
netty_unix_socket_setOption(env, fd, SOL_SOCKET, SO_BUSY_POLL, &optval, sizeof(optval));
|
||||
}
|
||||
|
||||
static void netty_epoll_linuxsocket_setTcpMd5Sig(JNIEnv* env, jclass clazz, jint fd, jbyteArray address, jint scopeId, jbyteArray key) {
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t addrSize;
|
||||
@ -256,6 +265,14 @@ static jint netty_epoll_linuxsocket_isTcpCork(JNIEnv* env, jclass clazz, jint fd
|
||||
return optval;
|
||||
}
|
||||
|
||||
static jint netty_epoll_linuxsocket_getSoBusyPoll(JNIEnv* env, jclass clazz, jint fd) {
|
||||
int optval;
|
||||
if (netty_unix_socket_getOption(env, fd, SOL_SOCKET, SO_BUSY_POLL, &optval, sizeof(optval)) == -1) {
|
||||
return -1;
|
||||
}
|
||||
return optval;
|
||||
}
|
||||
|
||||
static jint netty_epoll_linuxsocket_getTcpDeferAccept(JNIEnv* env, jclass clazz, jint fd) {
|
||||
int optval;
|
||||
if (netty_unix_socket_getOption(env, fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &optval, sizeof(optval)) == -1) {
|
||||
@ -341,10 +358,12 @@ static jlong netty_epoll_linuxsocket_sendFile(JNIEnv* env, jclass clazz, jint fd
|
||||
// JNI Method Registration Table Begin
|
||||
static const JNINativeMethod fixed_method_table[] = {
|
||||
{ "setTcpCork", "(II)V", (void *) netty_epoll_linuxsocket_setTcpCork },
|
||||
{ "setSoBusyPoll", "(II)V", (void *) netty_epoll_linuxsocket_setSoBusyPoll },
|
||||
{ "setTcpQuickAck", "(II)V", (void *) netty_epoll_linuxsocket_setTcpQuickAck },
|
||||
{ "setTcpDeferAccept", "(II)V", (void *) netty_epoll_linuxsocket_setTcpDeferAccept },
|
||||
{ "setTcpNotSentLowAt", "(II)V", (void *) netty_epoll_linuxsocket_setTcpNotSentLowAt },
|
||||
{ "isTcpCork", "(I)I", (void *) netty_epoll_linuxsocket_isTcpCork },
|
||||
{ "getSoBusyPoll", "(I)I", (void *) netty_epoll_linuxsocket_getSoBusyPoll },
|
||||
{ "getTcpDeferAccept", "(I)I", (void *) netty_epoll_linuxsocket_getTcpDeferAccept },
|
||||
{ "getTcpNotSentLowAt", "(I)I", (void *) netty_epoll_linuxsocket_getTcpNotSentLowAt },
|
||||
{ "isTcpQuickAck", "(I)I", (void *) netty_epoll_linuxsocket_isTcpQuickAck },
|
||||
|
@ -38,6 +38,7 @@ public final class EpollChannelOption<T> extends UnixChannelOption<T> {
|
||||
public static final ChannelOption<Integer> TCP_DEFER_ACCEPT =
|
||||
ChannelOption.valueOf(EpollChannelOption.class, "TCP_DEFER_ACCEPT");
|
||||
public static final ChannelOption<Boolean> TCP_QUICKACK = valueOf(EpollChannelOption.class, "TCP_QUICKACK");
|
||||
public static final ChannelOption<Integer> SO_BUSY_POLL = valueOf(EpollChannelOption.class, "SO_BUSY_POLL");
|
||||
|
||||
public static final ChannelOption<EpollMode> EPOLL_MODE =
|
||||
ChannelOption.valueOf(EpollChannelOption.class, "EPOLL_MODE");
|
||||
|
@ -62,7 +62,7 @@ public final class EpollSocketChannelConfig extends EpollChannelConfig implement
|
||||
ALLOW_HALF_CLOSURE, EpollChannelOption.TCP_CORK, EpollChannelOption.TCP_NOTSENT_LOWAT,
|
||||
EpollChannelOption.TCP_KEEPCNT, EpollChannelOption.TCP_KEEPIDLE, EpollChannelOption.TCP_KEEPINTVL,
|
||||
EpollChannelOption.TCP_MD5SIG, EpollChannelOption.TCP_QUICKACK, EpollChannelOption.IP_TRANSPARENT,
|
||||
EpollChannelOption.TCP_FASTOPEN_CONNECT);
|
||||
EpollChannelOption.TCP_FASTOPEN_CONNECT, EpollChannelOption.SO_BUSY_POLL);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@ -119,6 +119,9 @@ public final class EpollSocketChannelConfig extends EpollChannelConfig implement
|
||||
if (option == EpollChannelOption.TCP_FASTOPEN_CONNECT) {
|
||||
return (T) Boolean.valueOf(isTcpFastOpenConnect());
|
||||
}
|
||||
if (option == EpollChannelOption.SO_BUSY_POLL) {
|
||||
return (T) Integer.valueOf(getSoBusyPoll());
|
||||
}
|
||||
return super.getOption(option);
|
||||
}
|
||||
|
||||
@ -164,6 +167,8 @@ public final class EpollSocketChannelConfig extends EpollChannelConfig implement
|
||||
setTcpQuickAck((Boolean) value);
|
||||
} else if (option == EpollChannelOption.TCP_FASTOPEN_CONNECT) {
|
||||
setTcpFastOpenConnect((Boolean) value);
|
||||
} else if (option == EpollChannelOption.SO_BUSY_POLL) {
|
||||
setSoBusyPoll((Integer) value);
|
||||
} else {
|
||||
return super.setOption(option, value);
|
||||
}
|
||||
@ -245,6 +250,17 @@ public final class EpollSocketChannelConfig extends EpollChannelConfig implement
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@code SO_BUSY_POLL} option on the socket. See {@code man 7 tcp} for more details.
|
||||
*/
|
||||
public int getSoBusyPoll() {
|
||||
try {
|
||||
return channel.socket.getSoBusyPoll();
|
||||
} catch (IOException e) {
|
||||
throw new ChannelException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@code TCP_NOTSENT_LOWAT} option on the socket. See {@code man 7 tcp} for more details.
|
||||
* @return value is a uint32_t
|
||||
@ -380,6 +396,18 @@ public final class EpollSocketChannelConfig extends EpollChannelConfig implement
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@code SO_BUSY_POLL} option on the socket. See {@code man 7 tcp} for more details.
|
||||
*/
|
||||
public EpollSocketChannelConfig setSoBusyPoll(int loopMicros) {
|
||||
try {
|
||||
channel.socket.setSoBusyPoll(loopMicros);
|
||||
return this;
|
||||
} catch (IOException e) {
|
||||
throw new ChannelException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@code TCP_NOTSENT_LOWAT} option on the socket. See {@code man 7 tcp} for more details.
|
||||
* @param tcpNotSentLowAt is a uint32_t
|
||||
|
@ -56,6 +56,10 @@ final class LinuxSocket extends Socket {
|
||||
setTcpCork(intValue(), tcpCork ? 1 : 0);
|
||||
}
|
||||
|
||||
void setSoBusyPoll(int loopMicros) throws IOException {
|
||||
setSoBusyPoll(intValue(), loopMicros);
|
||||
}
|
||||
|
||||
void setTcpNotSentLowAt(long tcpNotSentLowAt) throws IOException {
|
||||
if (tcpNotSentLowAt < 0 || tcpNotSentLowAt > MAX_UINT32_T) {
|
||||
throw new IllegalArgumentException("tcpNotSentLowAt must be a uint32_t");
|
||||
@ -116,6 +120,10 @@ final class LinuxSocket extends Socket {
|
||||
return isTcpCork(intValue()) != 0;
|
||||
}
|
||||
|
||||
int getSoBusyPoll() throws IOException {
|
||||
return getSoBusyPoll(intValue());
|
||||
}
|
||||
|
||||
int getTcpDeferAccept() throws IOException {
|
||||
return getTcpDeferAccept(intValue());
|
||||
}
|
||||
@ -190,6 +198,7 @@ final class LinuxSocket extends Socket {
|
||||
private static native int getTcpDeferAccept(int fd) throws IOException;
|
||||
private static native int isTcpQuickAck(int fd) throws IOException;
|
||||
private static native int isTcpCork(int fd) throws IOException;
|
||||
private static native int getSoBusyPoll(int fd) throws IOException;
|
||||
private static native int getTcpNotSentLowAt(int fd) throws IOException;
|
||||
private static native int getTcpKeepIdle(int fd) throws IOException;
|
||||
private static native int getTcpKeepIntvl(int fd) throws IOException;
|
||||
@ -205,6 +214,7 @@ final class LinuxSocket extends Socket {
|
||||
private static native void setTcpDeferAccept(int fd, int deferAccept) throws IOException;
|
||||
private static native void setTcpQuickAck(int fd, int quickAck) throws IOException;
|
||||
private static native void setTcpCork(int fd, int tcpCork) throws IOException;
|
||||
private static native void setSoBusyPoll(int fd, int loopMicros) throws IOException;
|
||||
private static native void setTcpNotSentLowAt(int fd, int tcpNotSentLowAt) throws IOException;
|
||||
private static native void setTcpFastOpen(int fd, int tcpFastopenBacklog) throws IOException;
|
||||
private static native void setTcpFastOpenConnect(int fd, int tcpFastOpenConnect) throws IOException;
|
||||
|
Loading…
Reference in New Issue
Block a user