Skip to content

Commit

Permalink
Improve scan speed by avoiding division and modulus
Browse files Browse the repository at this point in the history
  • Loading branch information
fickludd committed May 25, 2018
1 parent 571a740 commit 83874f8
Show file tree
Hide file tree
Showing 9 changed files with 114 additions and 13 deletions.
Expand Up @@ -706,6 +706,12 @@ void node( NodeRecord record, long reference, PageCursor pageCursor )
nodes.getRecordByCursor( reference, record, RecordLoad.CHECK, pageCursor );
}

@Override
void nodeAdvance( NodeRecord record, PageCursor pageCursor )
{
nodes.nextRecordByCursor( record, RecordLoad.CHECK, pageCursor );
}

@Override
void relationship( RelationshipRecord record, long reference, PageCursor pageCursor )
{
Expand Down
Expand Up @@ -44,6 +44,7 @@ class DefaultNodeCursor extends NodeRecord implements NodeCursor
private PageCursor pageCursor;
private long next;
private long highMark;
private long nextStoreReference;
private HasChanges hasChanges = HasChanges.MAYBE;
private LongSet addedNodes;

Expand All @@ -67,6 +68,7 @@ void scan( Read read )
}
this.next = 0;
this.highMark = read.nodeHighMark();
this.nextStoreReference = NO_ID;
this.read = read;
this.hasChanges = HasChanges.MAYBE;
this.addedNodes = LongSets.immutable.empty();
Expand All @@ -85,6 +87,7 @@ void single( long reference, Read read )
this.next = reference;
//This marks the cursor as a "single cursor"
this.highMark = NO_ID;
this.nextStoreReference = NO_ID;
this.read = read;
this.hasChanges = HasChanges.MAYBE;
this.addedNodes = LongSets.immutable.empty();
Expand Down Expand Up @@ -225,9 +228,16 @@ else if ( hasChanges && txs.nodeIsDeletedInThisTx( next ) )
next++;
setInUse( false );
}
else if ( nextStoreReference == next )
{
read.nodeAdvance( this, pageCursor );
next++;
nextStoreReference++;
}
else
{
read.node( this, next++, pageCursor );
nextStoreReference = next;
}

if ( next > highMark )
Expand Down
Expand Up @@ -587,6 +587,8 @@ public final void futureRelationshipPropertyReferenceRead( long reference )

abstract void node( NodeRecord record, long reference, PageCursor pageCursor );

abstract void nodeAdvance( NodeRecord record, PageCursor pageCursor );

abstract void relationship( RelationshipRecord record, long reference, PageCursor pageCursor );

abstract void relationshipFull( RelationshipRecord record, long reference, PageCursor pageCursor );
Expand Down
Expand Up @@ -1042,7 +1042,6 @@ public void getRecordByCursor( long id, RECORD record, RecordLoad mode, PageCurs
{
throw new UnderlyingStorageException( e );
}

}

void readIntoRecord( long id, RECORD record, RecordLoad mode, PageCursor cursor ) throws IOException
Expand All @@ -1055,24 +1054,58 @@ void readIntoRecord( long id, RECORD record, RecordLoad mode, PageCursor cursor
int offset = offsetForId( id );
if ( cursor.next( pageId ) )
{
// There is a page in the store that covers this record, go read it
cursor.setOffset( offset );
cursor.mark();
do
{
prepareForReading( cursor, record );
recordFormat.read( record, cursor, mode, recordSize );
}
while ( cursor.shouldRetry() );
checkForDecodingErrors( cursor, id, mode );
verifyAfterReading( record, mode );
readRecordFromPage( id, record, mode, cursor );
}
else
{
verifyAfterNotRead( record, mode );
}
}

@Override
public void nextRecordByCursor( RECORD record, RecordLoad mode, PageCursor cursor ) throws UnderlyingStorageException
{
assert cursor.getOffset() % recordSize == 0 : "Cursor offset is record start";
assert cursor.getCurrentPageId() >= -1 : "Pages are assumed to be positive or -1 if not initialized";

try
{
int offset = cursor.getOffset();
long id = record.getId() + 1;
record.setId( id );
long pageId = cursor.getCurrentPageId();
if ( offset >= storeFile.pageSize() || pageId < 0 )
{
if ( !cursor.next( pageId + 1 ) )
{
verifyAfterNotRead( record, mode );
return;
}
cursor.setOffset( 0 );
}
readRecordFromPage( id, record, mode, cursor );
}
catch ( IOException e )
{
throw new UnderlyingStorageException( e );
}
}

private void readRecordFromPage( long id, RECORD record, RecordLoad mode, PageCursor cursor )
throws IOException
{
cursor.mark();
do
{
prepareForReading( cursor, record );
recordFormat.read( record, cursor, mode, recordSize );
}
while ( cursor.shouldRetry() );
checkForDecodingErrors( cursor, id, mode );
verifyAfterReading( record, mode );
}

@Override
public void updateRecord( RECORD record )
{
Expand Down
Expand Up @@ -130,6 +130,21 @@ public interface RecordStore<RECORD extends AbstractBaseRecord> extends IdSequen
*/
void getRecordByCursor( long id, RECORD target, RecordLoad mode, PageCursor cursor ) throws InvalidRecordException;

/**
* Reads a record from the store into {@code target}, see
* {@link RecordStore#getRecord(long, AbstractBaseRecord, RecordLoad)}.
* <p>
* This method requires that the cursor page and offset point to the first byte of the record in target on calling.
* The provided page cursor will be used to get the record, and in doing this it will be redirected to the
* next page if the input record was the last on it's page.
*
* @param target the record to fill.
* @param mode loading behaviour, read more in {@link RecordStore#getRecord(long, AbstractBaseRecord, RecordLoad)}.
* @param cursor the PageCursor to use for record loading.
* @throws InvalidRecordException if record not in use and the {@code mode} allows for throwing.
*/
void nextRecordByCursor( RECORD target, RecordLoad mode, PageCursor cursor ) throws InvalidRecordException;

/**
* For stores that have other stores coupled underneath, the "top level" record will have a flag
* saying whether or not it's light. Light means that no records from the coupled store have been loaded yet.
Expand Down Expand Up @@ -295,6 +310,12 @@ public void getRecordByCursor( long id, R target, RecordLoad mode, PageCursor cu
actual.getRecordByCursor( id, target, mode, cursor );
}

@Override
public void nextRecordByCursor( R target, RecordLoad mode, PageCursor cursor ) throws InvalidRecordException
{
actual.nextRecordByCursor( target, mode, cursor );
}

@Override
public Collection<R> getRecords( long firstId, RecordLoad mode ) throws InvalidRecordException
{
Expand Down
Expand Up @@ -19,8 +19,6 @@
*/
package org.neo4j.kernel.impl.store.format.standard;

import java.io.IOException;

import org.neo4j.io.pagecache.PageCursor;
import org.neo4j.kernel.impl.store.format.BaseOneByteHeaderRecordFormat;
import org.neo4j.kernel.impl.store.format.BaseRecordFormat;
Expand All @@ -32,6 +30,7 @@ public class NodeRecordFormat extends BaseOneByteHeaderRecordFormat<NodeRecord>
{
// in_use(byte)+next_rel_id(int)+next_prop_id(int)+labels(5)+extra(byte)
public static final int RECORD_SIZE = 15;
private static final int HEADER_SIZE = 1;

public NodeRecordFormat()
{
Expand Down Expand Up @@ -68,6 +67,11 @@ public void read( NodeRecord record, PageCursor cursor, RecordLoad mode, int rec
BaseRecordFormat.longFromIntAndMod( nextProp, propModifier ), dense,
BaseRecordFormat.longFromIntAndMod( nextRel, relModifier ), labels );
}
else
{
int nextOffset = cursor.getOffset() + recordSize - HEADER_SIZE;
cursor.setOffset( nextOffset );
}
}

@Override
Expand Down
Expand Up @@ -602,6 +602,22 @@ interface RecordReads<RECORD>
void getRecordByCursor( long reference, RECORD record, RecordLoad mode, PageCursor cursor )
throws InvalidRecordException;

/**
* Reads a record from the store into {@code target}, see
* {@link RecordStore#getRecord(long, AbstractBaseRecord, RecordLoad)}.
* <p>
* This method requires that the cursor page and offset point to the first byte of the record in target on calling.
* The provided page cursor will be used to get the record, and in doing this it will be redirected to the
* next page if the input record was the last on it's page.
*
* @param record the record to fill.
* @param mode loading behaviour, read more in {@link RecordStore#getRecord(long, AbstractBaseRecord, RecordLoad)}.
* @param cursor the PageCursor to use for record loading.
* @throws InvalidRecordException if record not in use and the {@code mode} allows for throwing.
*/
void nextRecordByCursor( RECORD record, RecordLoad mode, PageCursor cursor )
throws InvalidRecordException;

long getHighestPossibleIdInUse();
}

Expand Down
Expand Up @@ -579,6 +579,12 @@ void node( NodeRecord record, long reference, PageCursor pageCursor )
initialize( record, reference, nodes );
}

@Override
void nodeAdvance( NodeRecord record, PageCursor pageCursor )
{
initialize( record, record.getId() + 1, nodes );
}

@Override
void relationship( RelationshipRecord record, long reference, PageCursor pageCursor )
{
Expand Down
Expand Up @@ -160,6 +160,9 @@ public void read( RECORD record, PageCursor primaryCursor, RecordLoad mode, int
record.setUseFixedReferences( isUseFixedReferences( headerByte ) );
doReadInternal( record, primaryCursor, recordSize, headerByte, inUse );
}

// Set cursor offset to next record to prepare next read in case of scanning.
primaryCursor.setOffset( primaryStartOffset + recordSize );
}

private boolean isUseFixedReferences( byte headerByte )
Expand Down

0 comments on commit 83874f8

Please sign in to comment.