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:
parent
3feba1ece8
commit
2716a7be88
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue