ARTEMIS-2198 Reduce GC pressure on TransactionImpl and OperationContextImpl

TransactionImpl::properties are often not used and could be
avoided to be allocated.
OperationContextImpl.TaskHolders instances are turned into static
classes to avoid refecencing back the context, making the life
easier for the GC.
OperationContexImpl volatile loads can be reduced to make the
code faster on the hot path.
This commit is contained in:
Francesco Nigro 2018-12-07 10:36:29 +01:00 committed by Justin Bertram
parent 3feba1ece8
commit 2716a7be88
2 changed files with 42 additions and 23 deletions

View File

@ -140,6 +140,10 @@ public class OperationContextImpl implements OperationContext {
boolean executeNow = false;
synchronized (this) {
final int UNDEFINED = Integer.MIN_VALUE;
int storeLined = UNDEFINED;
int pageLined = UNDEFINED;
int replicationLined = UNDEFINED;
if (storeOnly) {
if (storeOnlyTasks == null) {
storeOnlyTasks = new LinkedList<>();
@ -147,16 +151,20 @@ public class OperationContextImpl implements OperationContext {
} else {
if (tasks == null) {
tasks = new LinkedList<>();
minimalReplicated = replicationLineUp.intValue();
minimalStore = storeLineUp.intValue();
minimalPage = pageLineUp.intValue();
minimalReplicated = (replicationLined = replicationLineUp.intValue());
minimalStore = (storeLined = storeLineUp.intValue());
minimalPage = (pageLined = pageLineUp.intValue());
}
}
//On the next branches each of them is been used
if (replicationLined == UNDEFINED) {
replicationLined = replicationLineUp.intValue();
storeLined = storeLineUp.intValue();
pageLined = pageLineUp.intValue();
}
// On this case, we can just execute the context directly
if (replicationLineUp.intValue() == replicated && storeLineUp.intValue() == stored &&
pageLineUp.intValue() == paged) {
if (replicationLined == replicated && storeLined == stored && pageLined == paged) {
// We want to avoid the executor if everything is complete...
// However, we can't execute the context if there are executions pending
// We need to use the executor on this case
@ -169,9 +177,9 @@ public class OperationContextImpl implements OperationContext {
}
} else {
if (storeOnly) {
storeOnlyTasks.add(new TaskHolder(completion));
storeOnlyTasks.add(new TaskHolder(completion, storeLined, replicationLined, pageLined));
} else {
tasks.add(new TaskHolder(completion));
tasks.add(new TaskHolder(completion, storeLined, replicationLined, pageLined));
}
}
}
@ -268,7 +276,7 @@ public class OperationContextImpl implements OperationContext {
}
}
final class TaskHolder {
static final class TaskHolder {
@Override
public String toString() {
@ -288,10 +296,10 @@ public class OperationContextImpl implements OperationContext {
final IOCallback task;
TaskHolder(final IOCallback task) {
storeLined = storeLineUp.intValue();
replicationLined = replicationLineUp.intValue();
pageLined = pageLineUp.intValue();
TaskHolder(final IOCallback task, int storeLined, int replicationLined, int pageLined) {
this.storeLined = storeLined;
this.replicationLined = replicationLined;
this.pageLined = pageLined;
this.task = task;
}
}
@ -349,4 +357,4 @@ public class OperationContextImpl implements OperationContext {
", executor=" + this.executor +
"]" + buffer.toString();
}
}
}

View File

@ -18,6 +18,7 @@ package org.apache.activemq.artemis.core.transaction.impl;
import javax.transaction.xa.Xid;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
@ -45,7 +46,7 @@ public class TransactionImpl implements Transaction {
private static final int INITIAL_NUM_PROPERTIES = 10;
private Object[] properties = new Object[TransactionImpl.INITIAL_NUM_PROPERTIES];
private Object[] properties = null;
protected final StorageManager storageManager;
@ -67,6 +68,22 @@ public class TransactionImpl implements Transaction {
private Object protocolData;
private void ensurePropertiesCapacity(int capacity) {
if (properties != null && properties.length >= capacity) {
return;
}
createOrEnlargeProperties(capacity);
}
private void createOrEnlargeProperties(int capacity) {
if (properties == null) {
properties = new Object[Math.min(TransactionImpl.INITIAL_NUM_PROPERTIES, capacity)];
} else {
assert properties.length < capacity;
properties = Arrays.copyOf(properties, capacity);
}
}
@Override
public Object getProtocolData() {
return protocolData;
@ -509,20 +526,14 @@ public class TransactionImpl implements Transaction {
@Override
public void putProperty(final int index, final Object property) {
if (index >= properties.length) {
Object[] newProperties = new Object[index];
System.arraycopy(properties, 0, newProperties, 0, properties.length);
properties = newProperties;
}
ensurePropertiesCapacity(index + 1);
properties[index] = property;
}
@Override
public Object getProperty(final int index) {
return properties[index];
return properties == null ? null : (index < properties.length ? properties[index] : null);
}
// Private