Minimize memory footprint for AbstractChannelHandlerContext for handlers that execute in the EventExecutor. (#8786)
Motivation: We cache the Runnable for some tasks to reduce GC pressure in 4 different fields. This gives overhead in terms of memory usage in all cases, even if we always execute in the EventExecutor (which is the case most of the times). Modifications: Move the 4 fields to another class and only have one reference to this in AbstractChannelHandlerContext. This gives a small overhead in the case of execution that is done outside of the EventExecutor but reduce memory footprint in the more likily execution case. Result: Less memory used per AbstractChannelHandlerContext in most cases.
This commit is contained in:
parent
e941cbe27a
commit
185efa5b7c
@ -116,10 +116,7 @@ abstract class AbstractChannelHandlerContext extends DefaultAttributeMap
|
||||
|
||||
// Lazily instantiated tasks used to trigger events to a handler with different executor.
|
||||
// There is no need to make this volatile as at worse it will just create a few more instances then needed.
|
||||
private Runnable invokeChannelReadCompleteTask;
|
||||
private Runnable invokeReadTask;
|
||||
private Runnable invokeChannelWritableStateChangedTask;
|
||||
private Runnable invokeFlushTask;
|
||||
private Tasks invokeTasks;
|
||||
|
||||
private volatile int handlerState = INIT;
|
||||
|
||||
@ -486,11 +483,11 @@ abstract class AbstractChannelHandlerContext extends DefaultAttributeMap
|
||||
if (executor.inEventLoop()) {
|
||||
next.invokeChannelReadComplete();
|
||||
} else {
|
||||
Runnable task = next.invokeChannelReadCompleteTask;
|
||||
if (task == null) {
|
||||
next.invokeChannelReadCompleteTask = task = next::invokeChannelReadComplete;
|
||||
Tasks tasks = next.invokeTasks;
|
||||
if (tasks == null) {
|
||||
next.invokeTasks = tasks = new Tasks(next);
|
||||
}
|
||||
executor.execute(task);
|
||||
executor.execute(tasks.invokeChannelReadCompleteTask);
|
||||
}
|
||||
}
|
||||
|
||||
@ -517,11 +514,11 @@ abstract class AbstractChannelHandlerContext extends DefaultAttributeMap
|
||||
if (executor.inEventLoop()) {
|
||||
next.invokeChannelWritabilityChanged();
|
||||
} else {
|
||||
Runnable task = next.invokeChannelWritableStateChangedTask;
|
||||
if (task == null) {
|
||||
next.invokeChannelWritableStateChangedTask = task = next::invokeChannelWritabilityChanged;
|
||||
Tasks tasks = next.invokeTasks;
|
||||
if (tasks == null) {
|
||||
next.invokeTasks = tasks = new Tasks(next);
|
||||
}
|
||||
executor.execute(task);
|
||||
executor.execute(tasks.invokeChannelWritableStateChangedTask);
|
||||
}
|
||||
}
|
||||
|
||||
@ -781,11 +778,11 @@ abstract class AbstractChannelHandlerContext extends DefaultAttributeMap
|
||||
if (executor.inEventLoop()) {
|
||||
next.invokeRead();
|
||||
} else {
|
||||
Runnable task = next.invokeReadTask;
|
||||
if (task == null) {
|
||||
next.invokeReadTask = task = next::invokeRead;
|
||||
Tasks tasks = next.invokeTasks;
|
||||
if (tasks == null) {
|
||||
next.invokeTasks = tasks = new Tasks(next);
|
||||
}
|
||||
executor.execute(task);
|
||||
executor.execute(tasks.invokeReadTask);
|
||||
}
|
||||
|
||||
return this;
|
||||
@ -838,11 +835,11 @@ abstract class AbstractChannelHandlerContext extends DefaultAttributeMap
|
||||
if (executor.inEventLoop()) {
|
||||
next.invokeFlush();
|
||||
} else {
|
||||
Runnable task = next.invokeFlushTask;
|
||||
if (task == null) {
|
||||
next.invokeFlushTask = task = next::invokeFlush;
|
||||
Tasks tasks = next.invokeTasks;
|
||||
if (tasks == null) {
|
||||
next.invokeTasks = tasks = new Tasks(next);
|
||||
}
|
||||
safeExecute(executor, task, channel().voidPromise(), null);
|
||||
safeExecute(executor, tasks.invokeFlushTask, channel().voidPromise(), null);
|
||||
}
|
||||
|
||||
return this;
|
||||
@ -1261,4 +1258,18 @@ abstract class AbstractChannelHandlerContext extends DefaultAttributeMap
|
||||
ctx.invokeFlush();
|
||||
}
|
||||
}
|
||||
|
||||
private static final class Tasks {
|
||||
private final Runnable invokeChannelReadCompleteTask;
|
||||
private final Runnable invokeReadTask;
|
||||
private final Runnable invokeChannelWritableStateChangedTask;
|
||||
private final Runnable invokeFlushTask;
|
||||
|
||||
Tasks(AbstractChannelHandlerContext next) {
|
||||
invokeChannelReadCompleteTask = next::invokeChannelReadComplete;
|
||||
invokeReadTask = next::invokeRead;
|
||||
invokeChannelWritableStateChangedTask = next::invokeChannelWritabilityChanged;
|
||||
invokeFlushTask = next::invokeFlush;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user