Reduce the memory footprint of DefaultChannelPromise even more (part 2)

- Rewirte DefaultChannelFutureListeners - this saves another int field when there are more then one listener.
This commit is contained in:
Trustin Lee 2013-02-26 14:43:12 -08:00
parent d8f5521210
commit 334b6c3129

View File

@ -20,7 +20,7 @@ import io.netty.util.Signal;
import io.netty.util.internal.InternalLogger; import io.netty.util.internal.InternalLogger;
import io.netty.util.internal.InternalLoggerFactory; import io.netty.util.internal.InternalLoggerFactory;
import java.util.ArrayList; import java.util.Arrays;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import static java.util.concurrent.TimeUnit.*; import static java.util.concurrent.TimeUnit.*;
@ -416,9 +416,7 @@ public class DefaultChannelPromise extends FlushCheckpoint implements ChannelPro
if (channel().eventLoop().inEventLoop()) { if (channel().eventLoop().inEventLoop()) {
if (listeners instanceof DefaultChannelPromiseListeners) { if (listeners instanceof DefaultChannelPromiseListeners) {
for (ChannelFutureListener l : (DefaultChannelPromiseListeners) listeners) { notifyListeners0(this, (DefaultChannelPromiseListeners) listeners);
notifyListener0(this, l);
}
} else { } else {
notifyListener0(this, (ChannelFutureListener) listeners); notifyListener0(this, (ChannelFutureListener) listeners);
} }
@ -430,9 +428,7 @@ public class DefaultChannelPromise extends FlushCheckpoint implements ChannelPro
@Override @Override
public void run() { public void run() {
if (listeners instanceof DefaultChannelPromiseListeners) { if (listeners instanceof DefaultChannelPromiseListeners) {
for (ChannelFutureListener l : (DefaultChannelPromiseListeners) listeners) { notifyListeners0(DefaultChannelPromise.this, (DefaultChannelPromiseListeners) listeners);
notifyListener0(DefaultChannelPromise.this, l);
}
} else { } else {
notifyListener0(DefaultChannelPromise.this, (ChannelFutureListener) listeners); notifyListener0(DefaultChannelPromise.this, (ChannelFutureListener) listeners);
} }
@ -441,6 +437,14 @@ public class DefaultChannelPromise extends FlushCheckpoint implements ChannelPro
} }
} }
private static void notifyListeners0(ChannelFuture f, DefaultChannelPromiseListeners listeners) {
final ChannelFutureListener[] a = listeners.listeners();
final int size = listeners.size();
for (int i = 0; i < size; i ++) {
notifyListener0(f, a[i]);
}
}
static void notifyListener(final ChannelFuture f, final ChannelFutureListener l) { static void notifyListener(final ChannelFuture f, final ChannelFutureListener l) {
EventLoop loop = f.channel().eventLoop(); EventLoop loop = f.channel().eventLoop();
if (loop.inEventLoop()) { if (loop.inEventLoop()) {
@ -514,13 +518,47 @@ public class DefaultChannelPromise extends FlushCheckpoint implements ChannelPro
return this; return this;
} }
private static final class DefaultChannelPromiseListeners extends ArrayList<ChannelFutureListener> { private static final class DefaultChannelPromiseListeners {
private static final long serialVersionUID = 7414281537694651180L; private ChannelFutureListener[] listeners;
private int size;
DefaultChannelPromiseListeners(ChannelFutureListener firstListener, ChannelFutureListener secondListener) { DefaultChannelPromiseListeners(ChannelFutureListener firstListener, ChannelFutureListener secondListener) {
super(2); listeners = new ChannelFutureListener[] { firstListener, secondListener };
add(firstListener); size = 2;
add(secondListener); }
void add(ChannelFutureListener l) {
ChannelFutureListener[] listeners = this.listeners;
final int size = this.size;
if (size == listeners.length) {
this.listeners = listeners = Arrays.copyOf(listeners, size << 1);
}
listeners[size] = l;
this.size = size + 1;
}
void remove(ChannelFutureListener l) {
final ChannelFutureListener[] listeners = this.listeners;
int size = this.size;
for (int i = 0; i < size; i ++) {
if (listeners[i] == l) {
int listenersToMove = size - i - 1;
if (listenersToMove > 0) {
System.arraycopy(listeners, i + 1, listeners, i, listenersToMove);
}
listeners[-- size] = null;
this.size = size;
return;
}
}
}
ChannelFutureListener[] listeners() {
return listeners;
}
int size() {
return size;
} }
} }
} }