Permalink
Browse files

o Cache refres to relationship types as ints instead of Strings.

o Binary search on sorted arrays for finding properties and relationship
  types in the cache.
o Less objects instantiated during getting and iterating relationships.
  • Loading branch information...
1 parent c07b712 commit f7133b838c3dbecf03702dc85341111c81682c6c @tinwelint committed Sep 2, 2012
@@ -22,6 +22,9 @@
import static org.neo4j.kernel.impl.cache.SizeOfs.withArrayOverheadIncludingReferences;
import static org.neo4j.kernel.impl.cache.SizeOfs.withObjectOverhead;
+import java.util.Arrays;
+import java.util.Comparator;
+
import org.neo4j.kernel.impl.cache.EntityWithSize;
import org.neo4j.kernel.impl.cache.SizeOfs;
import org.neo4j.kernel.impl.nioneo.store.PropertyData;
@@ -88,8 +91,23 @@ protected void setEmptyProperties()
{
result[i++] = property;
}
+ sort( result );
return result;
}
+
+ private static void sort( PropertyData[] array )
+ {
+ Arrays.sort( array, PROPERTY_DATA_COMPARATOR );
+ }
+
+ private static final Comparator<PropertyData> PROPERTY_DATA_COMPARATOR = new Comparator<PropertyData>()
+ {
+ @Override
+ public int compare( PropertyData o1, PropertyData o2 )
+ {
+ return o1.getIndex() - o2.getIndex();
+ }
+ };
@Override
public void setProperties( ArrayMap<Integer, PropertyData> properties, NodeManager nodeManager )
@@ -107,12 +125,25 @@ public void setProperties( ArrayMap<Integer, PropertyData> properties, NodeManag
@Override
protected PropertyData getPropertyForIndex( int keyId )
{
- for ( PropertyData property : properties )
+ PropertyData[] local = properties;
+
+ // Algorithm copied from java.util.Arrays#binarySearch
+ // Don't used used since the method signature makes it impossible
+ // to use for PropertyData objects (where we compare to PropertyData#getIndex()
+ int low = 0;
+ int high = local.length-1;
+ while ( low <= high )
{
- if ( property.getIndex() == keyId )
- {
- return property;
- }
+ int mid = (low + high) >>> 1;
+ PropertyData midVal = local[mid];
+ int midId = midVal.getIndex();
+
+ if ( midId < keyId )
+ low = mid + 1;
+ else if ( midId > keyId )
+ high = mid - 1;
+ else
+ return midVal; // key found
}
return null;
}
@@ -200,10 +231,12 @@ protected void commitPropertyMaps(
{
PropertyData[] compactedNewArray = new PropertyData[newArraySize];
System.arraycopy( newArray, 0, compactedNewArray, 0, newArraySize );
+ sort( compactedNewArray );
properties = compactedNewArray;
}
else
{
+ sort( newArray );
properties = newArray;
}
updateSize( nodeManager );
@@ -22,42 +22,42 @@
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
-import java.util.List;
import java.util.Map;
import org.neo4j.graphdb.NotFoundException;
import org.neo4j.graphdb.Relationship;
-import org.neo4j.graphdb.RelationshipType;
import org.neo4j.helpers.collection.PrefetchingIterator;
import org.neo4j.kernel.impl.util.RelIdArray;
import org.neo4j.kernel.impl.util.RelIdArray.DirectionWrapper;
import org.neo4j.kernel.impl.util.RelIdIterator;
class IntArrayIterator extends PrefetchingIterator<Relationship> implements Iterable<Relationship>
{
- private Iterator<RelIdIterator> typeIterator;
- private RelIdIterator currentTypeIterator;
+ private RelIdIterator[] rels;
+ private int currentTypeIndex;
private final NodeImpl fromNode;
private final DirectionWrapper direction;
private final NodeManager nodeManager;
- private final RelationshipType types[];
- private final List<RelIdIterator> rels;
// This is just for optimization
private boolean isFullyLoaded;
+ private final boolean allTypes;
- IntArrayIterator( List<RelIdIterator> rels, NodeImpl fromNode,
- DirectionWrapper direction, NodeManager nodeManager, RelationshipType[] types,
- boolean isFullyLoaded )
+ IntArrayIterator( RelIdIterator[] rels, NodeImpl fromNode,
+ DirectionWrapper direction, NodeManager nodeManager, boolean isFullyLoaded, boolean allTypes )
{
- this.rels = rels;
+ initializeRels( rels );
this.isFullyLoaded = isFullyLoaded;
- this.typeIterator = rels.iterator();
- this.currentTypeIterator = typeIterator.hasNext() ? typeIterator.next() : RelIdArray.EMPTY.iterator( direction );
this.fromNode = fromNode;
this.direction = direction;
this.nodeManager = nodeManager;
- this.types = types;
+ this.allTypes = allTypes;
+ }
+
+ private void initializeRels( RelIdIterator[] rels )
+ {
+ this.rels = rels;
+ this.currentTypeIndex = 0;
}
public Iterator<Relationship> iterator()
@@ -68,6 +68,7 @@
@Override
protected Relationship fetchNextOrNull()
{
+ RelIdIterator currentTypeIterator = rels[currentTypeIndex];
do
{
if ( currentTypeIterator.hasNext() )
@@ -84,9 +85,9 @@ protected Relationship fetchNextOrNull()
while ( !currentTypeIterator.hasNext() )
{
- if ( typeIterator.hasNext() )
+ if ( ++currentTypeIndex < rels.length )
{
- currentTypeIterator = typeIterator.next();
+ currentTypeIterator = rels[currentTypeIndex];
}
else if ( fromNode.getMoreRelationships( nodeManager ) ||
// This is here to guard for that someone else might have loaded
@@ -96,14 +97,14 @@ else if ( fromNode.getMoreRelationships( nodeManager ) ||
// isn't fully loaded when starting iterating.
!isFullyLoaded )
{
- Map<String,RelIdIterator> newRels = new HashMap<String,RelIdIterator>();
+ Map<Integer,RelIdIterator> newRels = new HashMap<Integer,RelIdIterator>();
for ( RelIdIterator itr : rels )
{
- String type = itr.getType();
+ int type = itr.getType();
RelIdArray newSrc = fromNode.getRelationshipIds( type );
if ( newSrc != null )
{
- itr = itr.updateSource( newSrc );
+ itr = itr.updateSource( newSrc, direction );
itr.doAnotherRound();
}
newRels.put( type, itr );
@@ -112,11 +113,11 @@ else if ( fromNode.getMoreRelationships( nodeManager ) ||
// If we wanted relationships of any type check if there are
// any new relationship types loaded for this node and if so
// initiate iterators for them
- if ( types.length == 0 )
+ if ( allTypes )
{
for ( RelIdArray ids : fromNode.getRelationshipIds() )
{
- String type = ids.getType();
+ int type = ids.getType();
RelIdIterator itr = newRels.get( type );
if ( itr == null )
{
@@ -127,18 +128,15 @@ else if ( fromNode.getMoreRelationships( nodeManager ) ||
}
else
{
- itr = itr.updateSource( ids );
+ itr = itr.updateSource( ids, direction );
newRels.put( type, itr );
}
}
}
- rels.clear();
- rels.addAll( newRels.values() );
-
- typeIterator = rels.iterator();
- currentTypeIterator = typeIterator.hasNext() ? typeIterator.next() : RelIdArray.EMPTY.iterator( direction );
+ initializeRels( newRels.values().toArray( new RelIdIterator[newRels.size()] ) );
isFullyLoaded = !fromNode.hasMoreRelationshipsToLoad();
+ currentTypeIterator = rels[currentTypeIndex];
}
else
{
@@ -150,18 +150,18 @@ private void assertNotDeleted()
private long firstRel = Record.NO_NEXT_RELATIONSHIP.intValue();
private long firstProp = Record.NO_NEXT_PROPERTY.intValue();
- private ArrayMap<String,RelIdArray> relationshipAddMap;
- private ArrayMap<String,Collection<Long>> relationshipRemoveMap;
+ private ArrayMap<Integer,RelIdArray> relationshipAddMap;
+ private ArrayMap<Integer,Collection<Long>> relationshipRemoveMap;
- public ArrayMap<String, RelIdArray> getRelationshipAddMap( boolean create )
+ public ArrayMap<Integer, RelIdArray> getRelationshipAddMap( boolean create )
{
- if ( relationshipAddMap == null && create ) relationshipAddMap = new ArrayMap<String, RelIdArray>();
+ if ( relationshipAddMap == null && create ) relationshipAddMap = new ArrayMap<Integer, RelIdArray>();
return relationshipAddMap;
}
- public RelIdArray getRelationshipAddMap( String type, boolean create )
+ public RelIdArray getRelationshipAddMap( int type, boolean create )
{
- ArrayMap<String, RelIdArray> map = getRelationshipAddMap( create );
+ ArrayMap<Integer, RelIdArray> map = getRelationshipAddMap( create );
if ( map == null ) return null;
RelIdArray result = map.get( type );
if ( result == null && create )
@@ -172,15 +172,15 @@ public RelIdArray getRelationshipAddMap( String type, boolean create )
return result;
}
- public ArrayMap<String, Collection<Long>> getRelationshipRemoveMap( boolean create )
+ public ArrayMap<Integer, Collection<Long>> getRelationshipRemoveMap( boolean create )
{
- if ( relationshipRemoveMap == null && create ) relationshipRemoveMap = new ArrayMap<String, Collection<Long>>();
+ if ( relationshipRemoveMap == null && create ) relationshipRemoveMap = new ArrayMap<Integer, Collection<Long>>();
return relationshipRemoveMap;
}
- public Collection<Long> getRelationshipRemoveMap( String type, boolean create )
+ public Collection<Long> getRelationshipRemoveMap( int type, boolean create )
{
- ArrayMap<String, Collection<Long>> map = getRelationshipRemoveMap( create );
+ ArrayMap<Integer, Collection<Long>> map = getRelationshipRemoveMap( create );
if ( map == null ) return null;
Collection<Long> result = map.get( type );
if ( result == null && create )
@@ -343,7 +343,7 @@ private Transaction getTransaction()
}
}
- public Collection<Long> getCowRelationshipRemoveMap( NodeImpl node, String type )
+ public Collection<Long> getCowRelationshipRemoveMap( NodeImpl node, int type )
{
PrimitiveElement primitiveElement = cowMap.get( getTransaction() );
if ( primitiveElement != null )
@@ -359,7 +359,7 @@ private Transaction getTransaction()
return null;
}
- public Collection<Long> getOrCreateCowRelationshipRemoveMap( NodeImpl node, String type )
+ public Collection<Long> getOrCreateCowRelationshipRemoveMap( NodeImpl node, int type )
{
return getPrimitiveElement( true ).nodeElement( node.getId(), true ).getRelationshipRemoveMap( type, true );
}
@@ -371,21 +371,21 @@ public void setFirstIds( long nodeId, long firstRel, long firstProp )
nodeElement.firstProp = firstProp;
}
- public ArrayMap<String,RelIdArray> getCowRelationshipAddMap( NodeImpl node )
+ public ArrayMap<Integer,RelIdArray> getCowRelationshipAddMap( NodeImpl node )
{
PrimitiveElement primitiveElement = getPrimitiveElement( false );
if ( primitiveElement == null ) return null;
CowNodeElement element = primitiveElement.nodeElement( node.getId(), false );
return element != null ? element.relationshipAddMap : null;
}
- public RelIdArray getCowRelationshipAddMap( NodeImpl node, String type )
+ public RelIdArray getCowRelationshipAddMap( NodeImpl node, int type )
{
- ArrayMap<String, RelIdArray> map = getCowRelationshipAddMap( node );
+ ArrayMap<Integer, RelIdArray> map = getCowRelationshipAddMap( node );
return map != null ? map.get( type ) : null;
}
- public RelIdArray getOrCreateCowRelationshipAddMap( NodeImpl node, String type )
+ public RelIdArray getOrCreateCowRelationshipAddMap( NodeImpl node, int type )
{
return getPrimitiveElement( true ).nodeElement( node.getId(), true ).getRelationshipAddMap( type, true );
}
@@ -740,15 +740,15 @@ private void populateNodeRelEvent( PrimitiveElement element,
}
if ( nodeElement.relationshipAddMap != null && !nodeElement.deleted )
{
- for ( String type : nodeElement.relationshipAddMap.keySet() )
+ for ( int type : nodeElement.relationshipAddMap.keySet() )
{
RelIdArray createdRels = nodeElement.relationshipAddMap.get( type );
populateNodeRelEvent( element, result, nodeId, createdRels );
}
}
if ( nodeElement.relationshipRemoveMap != null )
{
- for ( String type : nodeElement.relationshipRemoveMap.keySet() )
+ for ( int type : nodeElement.relationshipRemoveMap.keySet() )
{
Collection<Long> deletedRels = nodeElement.relationshipRemoveMap.get( type );
for ( long relId : deletedRels )
Oops, something went wrong.

0 comments on commit f7133b8

Please sign in to comment.