Fixed performance regression which occurs when a user tries to write something in channelConnected()
This commit is contained in:
parent
d7d0877ede
commit
cae3010d6e
@ -41,13 +41,17 @@ import org.jboss.netty.channel.ChannelSink;
|
||||
*/
|
||||
final class NioAcceptedSocketChannel extends NioSocketChannel {
|
||||
|
||||
final Thread bossThread;
|
||||
|
||||
NioAcceptedSocketChannel(
|
||||
ChannelFactory factory, ChannelPipeline pipeline,
|
||||
Channel parent, ChannelSink sink,
|
||||
SocketChannel socket, NioWorker worker) {
|
||||
SocketChannel socket, NioWorker worker, Thread bossThread) {
|
||||
|
||||
super(parent, factory, pipeline, sink, socket, worker);
|
||||
|
||||
this.bossThread = bossThread;
|
||||
|
||||
fireChannelOpen(this);
|
||||
fireChannelBound(this, getLocalAddress());
|
||||
fireChannelConnected(this, getRemoteAddress());
|
||||
|
@ -223,6 +223,8 @@ class NioServerSocketPipelineSink extends AbstractChannelSink {
|
||||
}
|
||||
|
||||
public void run() {
|
||||
final Thread currentThread = Thread.currentThread();
|
||||
|
||||
for (;;) {
|
||||
try {
|
||||
if (selector.select(1000) > 0) {
|
||||
@ -231,7 +233,7 @@ class NioServerSocketPipelineSink extends AbstractChannelSink {
|
||||
|
||||
SocketChannel acceptedSocket = channel.socket.accept();
|
||||
if (acceptedSocket != null) {
|
||||
registerAcceptedChannel(acceptedSocket);
|
||||
registerAcceptedChannel(acceptedSocket, currentThread);
|
||||
}
|
||||
} catch (SocketTimeoutException e) {
|
||||
// Thrown every second to get ClosedChannelException
|
||||
@ -257,7 +259,7 @@ class NioServerSocketPipelineSink extends AbstractChannelSink {
|
||||
closeSelector();
|
||||
}
|
||||
|
||||
private void registerAcceptedChannel(SocketChannel acceptedSocket) {
|
||||
private void registerAcceptedChannel(SocketChannel acceptedSocket, Thread currentThread) {
|
||||
try {
|
||||
ChannelPipeline pipeline =
|
||||
channel.getConfig().getPipelineFactory().getPipeline();
|
||||
@ -265,7 +267,7 @@ class NioServerSocketPipelineSink extends AbstractChannelSink {
|
||||
worker.register(new NioAcceptedSocketChannel(
|
||||
channel.getFactory(), pipeline, channel,
|
||||
NioServerSocketPipelineSink.this, acceptedSocket,
|
||||
worker), null);
|
||||
worker, currentThread), null);
|
||||
} catch (Exception e) {
|
||||
logger.warn(
|
||||
"Failed to initialize an accepted socket.", e);
|
||||
|
@ -363,23 +363,38 @@ class NioWorker implements Runnable {
|
||||
} else {
|
||||
writeNow(channel, channel.getConfig().getWriteSpinCount());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static boolean scheduleWriteIfNecessary(NioSocketChannel channel) {
|
||||
NioWorker worker = channel.worker;
|
||||
Thread workerThread = worker.thread;
|
||||
if (workerThread == null || Thread.currentThread() != workerThread) {
|
||||
private static boolean scheduleWriteIfNecessary(final NioSocketChannel channel) {
|
||||
final NioWorker worker = channel.worker;
|
||||
final Thread currentThread = Thread.currentThread();
|
||||
final Thread workerThread = worker.thread;
|
||||
if (workerThread == null || currentThread != workerThread) {
|
||||
if (channel.writeTaskInTaskQueue.compareAndSet(false, true)) {
|
||||
boolean offered = worker.writeTaskQueue.offer(channel.writeTask);
|
||||
assert offered;
|
||||
}
|
||||
Selector workerSelector = worker.selector;
|
||||
if (workerSelector != null) {
|
||||
if (worker.wakenUp.compareAndSet(false, true)) {
|
||||
workerSelector.wakeup();
|
||||
|
||||
if (!(channel instanceof NioAcceptedSocketChannel) ||
|
||||
((NioAcceptedSocketChannel) channel).bossThread != currentThread) {
|
||||
final Selector workerSelector = worker.selector;
|
||||
if (workerSelector != null) {
|
||||
if (worker.wakenUp.compareAndSet(false, true)) {
|
||||
workerSelector.wakeup();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// A write request can be made from an acceptor thread (boss)
|
||||
// when a user attempted to write something in:
|
||||
//
|
||||
// * channelOpen()
|
||||
// * channelBound()
|
||||
// * channelConnected().
|
||||
//
|
||||
// In this case, there's no need to wake up the selector because
|
||||
// the channel is not even registered yet at this moment.
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user