OPENJPA-2353: Reduce BitSet object allocations in StateManagerImpl.

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@1457966 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Richard G. Curtis 2013-03-18 20:13:10 +00:00
parent 70a201a55d
commit 47e402ce90
1 changed files with 73 additions and 32 deletions

View File

@ -114,8 +114,12 @@ public class StateManagerImpl implements OpenJPAStateManager, Serializable {
private transient PersistenceCapable _pc = null; private transient PersistenceCapable _pc = null;
protected transient ClassMetaData _meta = null; protected transient ClassMetaData _meta = null;
protected BitSet _loaded = null; protected BitSet _loaded = null;
// Care needs to be taken when accessing these fields as they will can be null if no fields are
// dirty, or have been flushed.
private BitSet _dirty = null; private BitSet _dirty = null;
private BitSet _flush = null; private BitSet _flush = null;
private BitSet _delayed = null; private BitSet _delayed = null;
private int _flags = 0; private int _flags = 0;
@ -351,9 +355,7 @@ public class StateManagerImpl implements OpenJPAStateManager, Serializable {
FieldMetaData[] fmds = _meta.getFields(); FieldMetaData[] fmds = _meta.getFields();
_loaded = new BitSet(fmds.length); _loaded = new BitSet(fmds.length);
_flush = new BitSet(fmds.length);
_dirty = new BitSet(fmds.length);
// mark primary key and non-persistent fields as loaded // mark primary key and non-persistent fields as loaded
for(int i : _meta.getPkAndNonPersistentManagedFmdIndexes()){ for(int i : _meta.getPkAndNonPersistentManagedFmdIndexes()){
_loaded.set(i); _loaded.set(i);
@ -491,14 +493,6 @@ public class StateManagerImpl implements OpenJPAStateManager, Serializable {
return _loaded; return _loaded;
} }
public BitSet getFlushed() {
return _flush;
}
public BitSet getDirty() {
return _dirty;
}
public BitSet getUnloaded(FetchConfiguration fetch) { public BitSet getUnloaded(FetchConfiguration fetch) {
// collect fields to load from data store based on fetch configuration // collect fields to load from data store based on fetch configuration
BitSet fields = getUnloadedInternal(fetch, LOAD_FGS, null); BitSet fields = getUnloadedInternal(fetch, LOAD_FGS, null);
@ -946,7 +940,7 @@ public class StateManagerImpl implements OpenJPAStateManager, Serializable {
lock(); lock();
try { try {
if (_saved == null || !_loaded.get(field) || !_dirty.get(field)) if (_saved == null || !_loaded.get(field) || !isFieldDirty(field))
return fetchField(field, false); return fetchField(field, false);
// if the field is dirty but we never loaded it, we can't restore it // if the field is dirty but we never loaded it, we can't restore it
@ -1060,8 +1054,11 @@ public class StateManagerImpl implements OpenJPAStateManager, Serializable {
boolean needPostUpdate = !(wasNew && !wasFlushed) boolean needPostUpdate = !(wasNew && !wasFlushed)
&& (ImplHelper.getUpdateFields(this) != null); && (ImplHelper.getUpdateFields(this) != null);
// all dirty fields were flushed // all dirty fields were flushed, we are referencing the _dirty BitSet directly here
_flush.or(_dirty); // because we don't want to instantiate it if we don't have to.
if (_dirty != null) {
getFlushed().or(_dirty);
}
// important to set flushed bit after calling _state.flush so // important to set flushed bit after calling _state.flush so
// that the state can tell whether this is the first flush // that the state can tell whether this is the first flush
@ -1108,7 +1105,7 @@ public class StateManagerImpl implements OpenJPAStateManager, Serializable {
void commit() { void commit() {
// release locks before oid updated // release locks before oid updated
releaseLocks(); releaseLocks();
// update version and oid information // update version and oid information
setVersion(_version); setVersion(_version);
_flags &= ~FLAG_FLUSHED; _flags &= ~FLAG_FLUSHED;
@ -1771,7 +1768,7 @@ public class StateManagerImpl implements OpenJPAStateManager, Serializable {
// note that the field is in need of flushing again, and tell the // note that the field is in need of flushing again, and tell the
// broker too // broker too
_flush.clear(field); clearFlushField(field);
_broker.setDirty(this, newFlush && !clean); _broker.setDirty(this, newFlush && !clean);
// save the field for rollback if needed // save the field for rollback if needed
@ -1779,9 +1776,9 @@ public class StateManagerImpl implements OpenJPAStateManager, Serializable {
// dirty the field and mark loaded; load fetch group if needed // dirty the field and mark loaded; load fetch group if needed
int lockLevel = calculateLockLevel(active, true, null); int lockLevel = calculateLockLevel(active, true, null);
if (!_dirty.get(field)) { if (!isFieldDirty(field)) {
setLoaded(field, true); setLoaded(field, true);
_dirty.set(field); setFieldDirty(field);
// make sure the field's fetch group is loaded // make sure the field's fetch group is loaded
if (loadFetchGroup && isPersistent() if (loadFetchGroup && isPersistent()
@ -2755,9 +2752,7 @@ public class StateManagerImpl implements OpenJPAStateManager, Serializable {
_flags &= ~FLAG_FLUSHED; _flags &= ~FLAG_FLUSHED;
_flags &= ~FLAG_FLUSHED_DIRTY; _flags &= ~FLAG_FLUSHED_DIRTY;
int fmds = _meta.getFields().length; _flush = null;
for (int i = 0; i < fmds; i++)
_flush.clear(i);
} }
/** /**
@ -2786,14 +2781,13 @@ public class StateManagerImpl implements OpenJPAStateManager, Serializable {
FieldMetaData[] fmds = _meta.getFields(); FieldMetaData[] fmds = _meta.getFields();
boolean update = !isNew() || isFlushed(); boolean update = !isNew() || isFlushed();
for (int i = 0; i < fmds.length; i++) { for (int i = 0; i < fmds.length; i++) {
if (val && (!update if (val && (!update || fmds[i].getUpdateStrategy() != UpdateStrategies.IGNORE))
|| fmds[i].getUpdateStrategy() != UpdateStrategies.IGNORE)) setFieldDirty(i);
_dirty.set(i);
else if (!val) { else if (!val) {
// we never consider clean fields flushed; this also takes // we never consider clean fields flushed; this also takes
// care of clearing the flushed fields on commit/rollback // care of clearing the flushed fields on commit/rollback
_flush.clear(i); clearFlushField(i);
_dirty.clear(i); clearDirty(i);
} }
} }
@ -2856,8 +2850,7 @@ public class StateManagerImpl implements OpenJPAStateManager, Serializable {
// record a saved field manager even if no field is currently loaded // record a saved field manager even if no field is currently loaded
// as existence of a SaveFieldManager is critical for a dirty check // as existence of a SaveFieldManager is critical for a dirty check
if (_saved == null) if (_saved == null)
_saved = new SaveFieldManager(this, getPersistenceCapable(), _saved = new SaveFieldManager(this, getPersistenceCapable(), getDirty());
_dirty);
} }
} }
@ -2880,7 +2873,7 @@ public class StateManagerImpl implements OpenJPAStateManager, Serializable {
// save the old field value anyway // save the old field value anyway
if (_saved == null) { if (_saved == null) {
if (_loaded.get(field)) if (_loaded.get(field))
_saved = new SaveFieldManager(this, null, _dirty); _saved = new SaveFieldManager(this, null, getDirty());
else else
return; return;
} }
@ -2961,7 +2954,7 @@ public class StateManagerImpl implements OpenJPAStateManager, Serializable {
for (FieldMetaData fmd : _meta.getProxyFields()) { for (FieldMetaData fmd : _meta.getProxyFields()) {
int index = fmd.getIndex(); int index = fmd.getIndex();
// only reload if dirty // only reload if dirty
if (_loaded.get(index) && _dirty.get(index)) { if (_loaded.get(index) && isFieldDirty(index)) {
provideField(_pc, _single, index); provideField(_pc, _single, index);
if (_single.proxy(reset, replaceNull)) { if (_single.proxy(reset, replaceNull)) {
replaceField(_pc, _single, index); replaceField(_pc, _single, index);
@ -3021,8 +3014,7 @@ public class StateManagerImpl implements OpenJPAStateManager, Serializable {
if (!logical) if (!logical)
assignObjectId(false, true); assignObjectId(false, true);
for (int i = 0, len = _meta.getFields().length; i < len; i++) { for (int i = 0, len = _meta.getFields().length; i < len; i++) {
if ((logical || !assignField(i, true)) && !_flush.get(i) if ((logical || !assignField(i, true)) && !isFieldFlushed(i) && isFieldDirty(i)) {
&& _dirty.get(i)) {
provideField(_pc, _single, i); provideField(_pc, _single, i);
if (_single.preFlush(logical, call)) if (_single.preFlush(logical, call))
replaceField(_pc, _single, i); replaceField(_pc, _single, i);
@ -3472,4 +3464,53 @@ public class StateManagerImpl implements OpenJPAStateManager, Serializable {
public void setBroker(BrokerImpl ctx) { public void setBroker(BrokerImpl ctx) {
_broker = ctx; _broker = ctx;
} }
public BitSet getFlushed() {
if (_flush == null) {
_flush = new BitSet(_meta.getFields().length);
}
return _flush;
}
private boolean isFieldFlushed(int index) {
if (_flush == null) {
return false;
}
return _flush.get(index);
}
/**
* Will clear the bit at the specified if the _flush BetSet has been created.
*/
private void clearFlushField(int index) {
if (_flush != null) {
getFlushed().clear(index);
}
}
public BitSet getDirty() {
if (_dirty == null) {
_dirty = new BitSet(_meta.getFields().length);
}
return _dirty;
}
private boolean isFieldDirty(int index) {
if (_dirty == null) {
return false;
}
return _dirty.get(index);
}
private void setFieldDirty(int index) {
getDirty().set(index);
}
/**
* Will clear the bit at the specified index if the _dirty BetSet has been created.
*/
private void clearDirty(int index) {
if (_dirty != null) {
getDirty().clear(index);
}
}
} }