Introduce HashedWheelTimer.pendingTimeouts()

Motivation:

Fixes #6681.

Modification:

For the sake of better timer observability, expose the number of pending timeouts through the new HashedWheelTimer.pendingTimeouts method .

Result:

It's now ridiculously easy to observe Netty timer's very basic and yet important metric, the number of pending tasks/timeouts.
This commit is contained in:
Vladimir Kostyukov 2017-04-27 23:42:18 -07:00 committed by Norman Maurer
parent 6915ec3bb9
commit ed37cf20ef
2 changed files with 32 additions and 15 deletions

View File

@ -16,7 +16,6 @@
package io.netty.util;
import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.StringUtil;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
@ -405,14 +404,14 @@ public class HashedWheelTimer implements Timer {
if (unit == null) {
throw new NullPointerException("unit");
}
if (shouldLimitTimeouts()) {
long pendingTimeoutsCount = pendingTimeouts.incrementAndGet();
if (pendingTimeoutsCount > maxPendingTimeouts) {
pendingTimeouts.decrementAndGet();
throw new RejectedExecutionException("Number of pending timeouts ("
+ pendingTimeoutsCount + ") is greater than or equal to maximum allowed pending "
+ "timeouts (" + maxPendingTimeouts + ")");
}
long pendingTimeoutsCount = pendingTimeouts.incrementAndGet();
if (maxPendingTimeouts > 0 && pendingTimeoutsCount > maxPendingTimeouts) {
pendingTimeouts.decrementAndGet();
throw new RejectedExecutionException("Number of pending timeouts ("
+ pendingTimeoutsCount + ") is greater than or equal to maximum allowed pending "
+ "timeouts (" + maxPendingTimeouts + ")");
}
start();
@ -425,8 +424,11 @@ public class HashedWheelTimer implements Timer {
return timeout;
}
private boolean shouldLimitTimeouts() {
return maxPendingTimeouts > 0;
/**
* Returns the number of pending timeouts of this {@link Timer}.
*/
public long pendingTimeouts() {
return pendingTimeouts.get();
}
private static void reportTooManyInstances() {
@ -629,7 +631,7 @@ public class HashedWheelTimer implements Timer {
HashedWheelBucket bucket = this.bucket;
if (bucket != null) {
bucket.remove(this);
} else if (timer.shouldLimitTimeouts()) {
} else {
timer.pendingTimeouts.decrementAndGet();
}
}
@ -774,9 +776,7 @@ public class HashedWheelTimer implements Timer {
timeout.prev = null;
timeout.next = null;
timeout.bucket = null;
if (timeout.timer.shouldLimitTimeouts()) {
timeout.timer.pendingTimeouts.decrementAndGet();
}
timeout.timer.pendingTimeouts.decrementAndGet();
return next;
}

View File

@ -213,6 +213,23 @@ public class HashedWheelTimerTest {
timer.stop();
}
@Test()
public void reportPendingTimeouts() throws InterruptedException {
final CountDownLatch latch = new CountDownLatch(1);
final HashedWheelTimer timer = new HashedWheelTimer();
final Timeout t1 = timer.newTimeout(createNoOpTimerTask(), 100, TimeUnit.MINUTES);
final Timeout t2 = timer.newTimeout(createNoOpTimerTask(), 100, TimeUnit.MINUTES);
timer.newTimeout(createCountDownLatchTimerTask(latch), 90, TimeUnit.MILLISECONDS);
assertEquals(3, timer.pendingTimeouts());
t1.cancel();
t2.cancel();
latch.await();
assertEquals(0, timer.pendingTimeouts());
timer.stop();
}
private static TimerTask createNoOpTimerTask() {
return new TimerTask() {
@Override