Selector auto-rebuilder tweaks

This commit is contained in:
Trustin Lee 2013-03-22 12:37:11 +09:00
parent ffdc2a6b11
commit 34853e7ba0

View File

@ -56,8 +56,7 @@ public final class NioEventLoop extends SingleThreadEventLoop {
private static final int CLEANUP_INTERVAL = 256; // XXX Hard-coded value, but won't need customization. private static final int CLEANUP_INTERVAL = 256; // XXX Hard-coded value, but won't need customization.
private static final int SELECTOR_AUTO_REBUILD_THRESHOLD = private static final int SELECTOR_AUTO_REBUILD_THRESHOLD;
SystemPropertyUtil.getInt("io.netty.selectorAutoRebuildThreshold", 16);
// Workaround for JDK NIO bug. // Workaround for JDK NIO bug.
// //
@ -77,6 +76,13 @@ public final class NioEventLoop extends SingleThreadEventLoop {
} }
} }
int selectorAutoRebuildThreshold = SystemPropertyUtil.getInt("io.netty.selectorAutoRebuildThreshold", 16);
if (selectorAutoRebuildThreshold < 2) {
selectorAutoRebuildThreshold = 0;
}
SELECTOR_AUTO_REBUILD_THRESHOLD = selectorAutoRebuildThreshold;
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Selector auto-rebuild threshold: {}", SELECTOR_AUTO_REBUILD_THRESHOLD); logger.debug("Selector auto-rebuild threshold: {}", SELECTOR_AUTO_REBUILD_THRESHOLD);
} }
@ -96,6 +102,7 @@ public final class NioEventLoop extends SingleThreadEventLoop {
* waken up. * waken up.
*/ */
private final AtomicBoolean wakenUp = new AtomicBoolean(); private final AtomicBoolean wakenUp = new AtomicBoolean();
private boolean oldWakenUp;
private volatile int ioRatio = 50; private volatile int ioRatio = 50;
private int cancelledKeys; private int cancelledKeys;
@ -127,6 +134,12 @@ public final class NioEventLoop extends SingleThreadEventLoop {
return new ConcurrentLinkedQueue<Runnable>(); return new ConcurrentLinkedQueue<Runnable>();
} }
@Override
protected boolean hasTasks() {
// ConcurrentLinkedQueue.isEmpty() is not accurate enough when tasks are added from different threads.
return peekTask() != null;
}
/** /**
* Registers an arbitrary {@link SelectableChannel}, not necessarily created by Netty, to the {@link Selector} * Registers an arbitrary {@link SelectableChannel}, not necessarily created by Netty, to the {@link Selector}
* of this event loop. Once the specified {@link SelectableChannel} is registered, the specified {@code task} will * of this event loop. Once the specified {@link SelectableChannel} is registered, the specified {@code task} will
@ -275,8 +288,7 @@ public final class NioEventLoop extends SingleThreadEventLoop {
@Override @Override
protected void run() { protected void run() {
for (;;) { for (;;) {
wakenUp.set(false); oldWakenUp = wakenUp.getAndSet(false);
try { try {
if (hasTasks()) { if (hasTasks()) {
selectNow(); selectNow();
@ -559,7 +571,7 @@ public final class NioEventLoop extends SingleThreadEventLoop {
if (delayMillis > 0) { if (delayMillis > 0) {
long startTimeNanos = System.nanoTime(); long startTimeNanos = System.nanoTime();
if (selector.select(delayMillis) == 0) { if (selector.select(delayMillis) == 0) {
if (wakenUp.get() || hasTasks()) { if (oldWakenUp || wakenUp.get() || hasTasks()) {
// Waken up by user or the task queue has a pending task. // Waken up by user or the task queue has a pending task.
return; return;
} }
@ -581,8 +593,8 @@ public final class NioEventLoop extends SingleThreadEventLoop {
logger.warn( logger.warn(
"Selector.select() returned prematurely {} times in a row; rebuilding selector.", "Selector.select() returned prematurely {} times in a row; rebuilding selector.",
prematureSelectorReturns); prematureSelectorReturns);
rebuildSelector(); rebuildSelector();
selector = this.selector;
// Select again to populate selectedKeys. // Select again to populate selectedKeys.
selector.selectNow(); selector.selectNow();
@ -591,7 +603,6 @@ public final class NioEventLoop extends SingleThreadEventLoop {
resetPrematureSelectorReturns(); resetPrematureSelectorReturns();
} }
} else { } else {
// reset counter
resetPrematureSelectorReturns(); resetPrematureSelectorReturns();
} }
} else { } else {
@ -601,9 +612,7 @@ public final class NioEventLoop extends SingleThreadEventLoop {
} }
} catch (CancelledKeyException e) { } catch (CancelledKeyException e) {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug( logger.debug(CancelledKeyException.class.getSimpleName() + " raised by a Selector - JDK bug?", e);
CancelledKeyException.class.getSimpleName() +
" raised by a Selector - JDK bug?", e);
} }
// Harmless exception - log anyway // Harmless exception - log anyway
} }
@ -622,7 +631,7 @@ public final class NioEventLoop extends SingleThreadEventLoop {
private void resetPrematureSelectorReturns() { private void resetPrematureSelectorReturns() {
int prematureSelectorReturns = this.prematureSelectorReturns; int prematureSelectorReturns = this.prematureSelectorReturns;
if (prematureSelectorReturns != 0) { if (prematureSelectorReturns > 1) {
if (logger.isWarnEnabled()) { if (logger.isWarnEnabled()) {
logger.warn("Selector.select() returned prematurely {} times in a row.", prematureSelectorReturns); logger.warn("Selector.select() returned prematurely {} times in a row.", prematureSelectorReturns);
} }