Fixed excessive CPU consumption

This commit is contained in:
Trustin Lee 2009-01-20 09:03:31 +00:00
parent 3e0d1f69b0
commit 11f7606b6d

View File

@ -155,17 +155,14 @@ public class HashedWheelTimer implements Timer {
// Add the timeout to the wheel. // Add the timeout to the wheel.
HashedWheelTimeout timeout; HashedWheelTimeout timeout;
long currentTime = System.nanoTime();
lock.readLock().lock(); lock.readLock().lock();
try { try {
timeout = new HashedWheelTimeout( timeout = new HashedWheelTimeout(
task, wheelCursor, System.nanoTime(), initialDelay); task, wheelCursor, currentTime, initialDelay);
wheel[schedule(timeout)].add(timeout); wheel[schedule(timeout)].add(timeout);
increaseActiveTimeouts();
// Start the worker if necessary.
if (activeTimeouts.getAndIncrement() == 0) {
executor.execute(worker);
}
} finally { } finally {
lock.readLock().unlock(); lock.readLock().unlock();
} }
@ -173,6 +170,13 @@ public class HashedWheelTimer implements Timer {
return timeout; return timeout;
} }
void increaseActiveTimeouts() {
// Start the worker if necessary.
if (activeTimeouts.getAndIncrement() == 0) {
executor.execute(worker);
}
}
private int schedule(HashedWheelTimeout timeout) { private int schedule(HashedWheelTimeout timeout) {
return schedule(timeout, timeout.initialDelay); return schedule(timeout, timeout.initialDelay);
} }
@ -217,6 +221,8 @@ public class HashedWheelTimer implements Timer {
private final class Worker implements Runnable { private final class Worker implements Runnable {
private volatile long threadSafeStartTime; private volatile long threadSafeStartTime;
private volatile long threadSafeTick;
private long startTime;
private long tick; private long tick;
Worker() { Worker() {
@ -227,15 +233,24 @@ public class HashedWheelTimer implements Timer {
List<HashedWheelTimeout> expiredTimeouts = List<HashedWheelTimeout> expiredTimeouts =
new ArrayList<HashedWheelTimeout>(); new ArrayList<HashedWheelTimeout>();
long startTime = threadSafeStartTime; startTime = threadSafeStartTime;
tick = 1; tick = threadSafeTick;
if (startTime == 0) {
startTime = System.nanoTime();
tick = 1;
}
boolean continueTheLoop; try {
do { boolean continueTheLoop;
startTime = waitForNextTick(startTime); do {
continueTheLoop = fetchExpiredTimeouts(expiredTimeouts); startTime = waitForNextTick();
notifyExpiredTimeouts(expiredTimeouts); continueTheLoop = fetchExpiredTimeouts(expiredTimeouts);
} while (continueTheLoop && !ExecutorUtil.isShutdown(executor)); notifyExpiredTimeouts(expiredTimeouts);
} while (continueTheLoop && !ExecutorUtil.isShutdown(executor));
} finally{
threadSafeStartTime = startTime;
threadSafeTick = tick;
}
} }
private boolean fetchExpiredTimeouts( private boolean fetchExpiredTimeouts(
@ -277,27 +292,24 @@ public class HashedWheelTimer implements Timer {
ReusableIterator<HashedWheelTimeout> i) { ReusableIterator<HashedWheelTimeout> i) {
long currentTime = System.nanoTime(); long currentTime = System.nanoTime();
boolean notEmpty = i.hasNext(); i.rewind();
if (notEmpty) { while (i.hasNext()) {
do { HashedWheelTimeout timeout = i.next();
HashedWheelTimeout timeout = i.next(); synchronized (timeout) {
synchronized (timeout) { if (timeout.remainingRounds <= 0) {
if (timeout.remainingRounds <= 0) { if (timeout.deadline <= currentTime) {
if (timeout.deadline <= currentTime) { i.remove();
i.remove(); expiredTimeouts.add(timeout);
expiredTimeouts.add(timeout); activeTimeouts.getAndDecrement();
activeTimeouts.getAndDecrement();
} else {
// A rare case where a timeout is put for the next
// round: just wait for the next round.
timeout.slippedRounds ++;
}
} else { } else {
timeout.remainingRounds --; // A rare case where a timeout is put for the next
// round: just wait for the next round.
timeout.slippedRounds ++;
} }
} else {
timeout.remainingRounds --;
} }
} while (i.hasNext()); }
i.rewind();
} }
} }
@ -312,7 +324,7 @@ public class HashedWheelTimer implements Timer {
expiredTimeouts.clear(); expiredTimeouts.clear();
} }
private long waitForNextTick(long startTime) { private long waitForNextTick() {
for (;;) { for (;;) {
final long currentTime = System.nanoTime(); final long currentTime = System.nanoTime();
final long sleepTime = tickDuration * tick - (currentTime - startTime); final long sleepTime = tickDuration * tick - (currentTime - startTime);
@ -411,11 +423,7 @@ public class HashedWheelTimer implements Timer {
} }
if (wheel[newStopIndex].add(this)) { if (wheel[newStopIndex].add(this)) {
increaseActiveTimeouts();
// Start the worker if necessary.
if (activeTimeouts.getAndIncrement() == 0) {
executor.execute(worker);
}
} }
} finally { } finally {
extensionCount ++; extensionCount ++;
@ -514,12 +522,12 @@ public class HashedWheelTimer implements Timer {
for (int i = 0; i < 1; i ++) { for (int i = 0; i < 1; i ++) {
timer.newTimeout(new TimerTask() { timer.newTimeout(new TimerTask() {
public void run(Timeout timeout) throws Exception { public void run(Timeout timeout) throws Exception {
//System.out.println(Thread.currentThread().getName() + ": " + timeout.getExtensionCount() + ": " + timeout); System.out.println(Thread.currentThread().getName() + ": " + timeout.getExtensionCount() + ": " + timeout);
timeout.extend(); timeout.extend();
int c = e.getActiveCount(); int c = e.getActiveCount();
if (c > 1) { // if (c > 1) {
System.out.println(System.currentTimeMillis() + ": " + c); // System.out.println(System.currentTimeMillis() + ": " + c);
} // }
} }
}, 100, TimeUnit.MILLISECONDS); }, 100, TimeUnit.MILLISECONDS);
} }