Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use cursor directly instead of intermediate iterator
By having direct access to the cursor we can get a significant speedup instead of delegating via an iterator when doing label scans.
- Loading branch information
1 parent
de44791
commit 3a2a6d2
Showing
7 changed files
with
324 additions
and
79 deletions.
There are no files selected for viewing
102 changes: 102 additions & 0 deletions
102
...rnel/src/main/java/org/neo4j/kernel/impl/index/labelscan/LabelScanValueIndexAccessor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
/* | ||
* Copyright (c) 2002-2018 "Neo Technology," | ||
* Network Engine for Objects in Lund AB [http://neotechnology.com] | ||
* | ||
* This file is part of Neo4j. | ||
* | ||
* Neo4j is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
package org.neo4j.kernel.impl.index.labelscan; | ||
|
||
import java.io.IOException; | ||
import java.io.UncheckedIOException; | ||
import java.util.Collection; | ||
|
||
import org.neo4j.cursor.RawCursor; | ||
import org.neo4j.index.internal.gbptree.Hit; | ||
|
||
/** | ||
* Base class for iterator and index-progressor of label scans. | ||
*/ | ||
abstract class LabelScanValueIndexAccessor | ||
{ | ||
/** | ||
* {@link RawCursor} to lazily read new {@link LabelScanValue} from. | ||
*/ | ||
protected final RawCursor<Hit<LabelScanKey,LabelScanValue>,IOException> cursor; | ||
/** | ||
* Remove provided cursor from this collection when iterator is exhausted. | ||
*/ | ||
private final Collection<RawCursor<Hit<LabelScanKey,LabelScanValue>,IOException>> toRemoveFromWhenClosed; | ||
/** | ||
* Current base nodeId, i.e. the {@link LabelScanKey#idRange} of the current {@link LabelScanKey}. | ||
*/ | ||
long baseNodeId; | ||
/** | ||
* Bit set of the current {@link LabelScanValue}. | ||
*/ | ||
protected long bits; | ||
/** | ||
* LabelId of previously retrieved {@link LabelScanKey}, for debugging and asserting purposes. | ||
*/ | ||
private int prevLabel = -1; | ||
/** | ||
* IdRange of previously retrieved {@link LabelScanKey}, for debugging and asserting purposes. | ||
*/ | ||
private long prevRange = -1; | ||
/** | ||
* Indicate provided cursor has been closed. | ||
*/ | ||
private boolean closed; | ||
|
||
LabelScanValueIndexAccessor( | ||
Collection<RawCursor<Hit<LabelScanKey,LabelScanValue>,IOException>> toRemoveFromWhenClosed, | ||
RawCursor<Hit<LabelScanKey,LabelScanValue>,IOException> cursor ) | ||
{ | ||
this.toRemoveFromWhenClosed = toRemoveFromWhenClosed; | ||
this.cursor = cursor; | ||
} | ||
|
||
boolean keysInOrder( LabelScanKey key ) | ||
{ | ||
assert key.labelId >= prevLabel : "Expected to get ordered results, got " + key + | ||
" where previous label was " + prevLabel; | ||
assert key.idRange > prevRange : "Expected to get ordered results, got " + key + | ||
" where previous range was " + prevRange; | ||
prevLabel = key.labelId; | ||
prevRange = key.idRange; | ||
// Made as a method returning boolean so that it can participate in an assert call. | ||
return true; | ||
} | ||
|
||
public void close() | ||
{ | ||
if ( !closed ) | ||
{ | ||
try | ||
{ | ||
cursor.close(); | ||
} | ||
catch ( IOException e ) | ||
{ | ||
throw new UncheckedIOException( e ); | ||
} | ||
finally | ||
{ | ||
toRemoveFromWhenClosed.remove( cursor ); | ||
closed = true; | ||
} | ||
} | ||
} | ||
} |
89 changes: 89 additions & 0 deletions
89
...el/src/main/java/org/neo4j/kernel/impl/index/labelscan/LabelScanValueIndexProgressor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
/* | ||
* Copyright (c) 2002-2018 "Neo Technology," | ||
* Network Engine for Objects in Lund AB [http://neotechnology.com] | ||
* | ||
* This file is part of Neo4j. | ||
* | ||
* Neo4j is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
package org.neo4j.kernel.impl.index.labelscan; | ||
|
||
import java.io.IOException; | ||
import java.io.UncheckedIOException; | ||
import java.util.Collection; | ||
|
||
import org.neo4j.cursor.RawCursor; | ||
import org.neo4j.graphdb.Resource; | ||
import org.neo4j.index.internal.gbptree.Hit; | ||
import org.neo4j.storageengine.api.schema.IndexProgressor; | ||
|
||
/** | ||
* {@link IndexProgressor} which steps over multiple {@link LabelScanValue} and for each | ||
* iterate over each set bit, returning actual node ids, i.e. {@code nodeIdRange+bitOffset}. | ||
* | ||
*/ | ||
class LabelScanValueIndexProgressor extends LabelScanValueIndexAccessor implements IndexProgressor, Resource | ||
{ | ||
|
||
private final NodeLabelClient client; | ||
|
||
LabelScanValueIndexProgressor( RawCursor<Hit<LabelScanKey,LabelScanValue>,IOException> cursor, | ||
Collection<RawCursor<Hit<LabelScanKey,LabelScanValue>,IOException>> toRemoveFromWhenClosed, | ||
NodeLabelClient client ) | ||
{ | ||
super( toRemoveFromWhenClosed, cursor ); | ||
this.client = client; | ||
} | ||
|
||
/** | ||
* @return next node id in the current {@link LabelScanValue} or, if current value exhausted, | ||
* goes to next {@link LabelScanValue} from {@link RawCursor}. Returns {@code true} if next node id | ||
* was found, otherwise {@code false}. | ||
*/ | ||
@Override | ||
public boolean next() | ||
{ | ||
while ( true ) | ||
{ | ||
if ( bits != 0 ) | ||
{ | ||
int delta = Long.numberOfTrailingZeros( bits ); | ||
bits &= bits - 1; | ||
if ( client.acceptNode( baseNodeId + delta, null ) ) | ||
{ | ||
return true; | ||
} | ||
} | ||
try | ||
{ | ||
if ( !cursor.next() ) | ||
{ | ||
close(); | ||
return false; | ||
} | ||
} | ||
catch ( IOException e ) | ||
{ | ||
throw new UncheckedIOException( e ); | ||
} | ||
|
||
Hit<LabelScanKey,LabelScanValue> hit = cursor.get(); | ||
baseNodeId = hit.key().idRange * LabelScanValue.RANGE_SIZE; | ||
bits = hit.value().bits; | ||
|
||
//noinspection AssertWithSideEffects | ||
assert keysInOrder( hit.key() ); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.