Skip to content

Commit

Permalink
Speed up bounds checking on non-offsetted page accesses
Browse files Browse the repository at this point in the history
This is possible because we can ignore the underflow case when using the implied offset
  • Loading branch information
chrisvest committed May 26, 2017
1 parent 61f103e commit a0abeff
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 11 deletions.
Expand Up @@ -407,10 +407,29 @@ private long getBoundedPointer( int offset, int size )
}
}

/**
* Compute a pointer that guarantees (assuming {@code size} is less than or equal to {@link #pageSize}) that the
* page access will be within the bounds of the page.
* This works just like {@link #getBoundedPointer(int, int)}, except in terms of the current {@link #offset}.
* This version is faster when applicable, because it can ignore the <em>page underflow</em> case.
*/
private long nextBoundedPointer( int size )
{
if ( boundsCheck )
{
outOfBounds |= offset + size > pageSize;
return outOfBounds? pointer : pointer + offset;
}
else
{
return pointer + offset;
}
}

@Override
public final byte getByte()
{
long p = getBoundedPointer( offset, SIZE_OF_BYTE );
long p = nextBoundedPointer( SIZE_OF_BYTE );
byte b = UnsafeUtil.getByte( p );
offset++;
return b;
Expand All @@ -426,7 +445,7 @@ public byte getByte( int offset )
@Override
public void putByte( byte value )
{
long p = getBoundedPointer( offset, SIZE_OF_BYTE );
long p = nextBoundedPointer( SIZE_OF_BYTE );
UnsafeUtil.putByte( p, value );
offset++;
}
Expand All @@ -441,7 +460,8 @@ public void putByte( int offset, byte value )
@Override
public long getLong()
{
long value = getLong( offset );
long p = nextBoundedPointer( SIZE_OF_LONG );
long value = getLongAt( p );
offset += SIZE_OF_LONG;
return value;
}
Expand All @@ -450,6 +470,11 @@ public long getLong()
public long getLong( int offset )
{
long p = getBoundedPointer( offset, SIZE_OF_LONG );
return getLongAt( p );
}

private long getLongAt( long p )
{
long value;
if ( UnsafeUtil.allowUnalignedMemoryAccess )
{
Expand Down Expand Up @@ -482,14 +507,20 @@ private long getLongBigEndian( long p )
@Override
public void putLong( long value )
{
putLong( offset, value );
long p = nextBoundedPointer( SIZE_OF_LONG );
putLongAt( p, value );
offset += SIZE_OF_LONG;
}

@Override
public void putLong( int offset, long value )
{
long p = getBoundedPointer( offset, SIZE_OF_LONG );
putLongAt( p, value );
}

private void putLongAt( long p, long value )
{
if ( UnsafeUtil.allowUnalignedMemoryAccess )
{
UnsafeUtil.putLong( p, UnsafeUtil.storeByteOrderIsNative ? value : Long.reverseBytes( value ) );
Expand All @@ -515,7 +546,8 @@ private void putLongBigEndian( long value, long p )
@Override
public int getInt()
{
int i = getInt( offset );
long p = nextBoundedPointer( SIZE_OF_INT );
int i = getIntAt( p );
offset += SIZE_OF_INT;
return i;
}
Expand All @@ -524,6 +556,11 @@ public int getInt()
public int getInt( int offset )
{
long p = getBoundedPointer( offset, SIZE_OF_INT );
return getIntAt( p );
}

private int getIntAt( long p )
{
if ( UnsafeUtil.allowUnalignedMemoryAccess )
{
int x = UnsafeUtil.getInt( p );
Expand All @@ -544,14 +581,20 @@ private int getIntBigEndian( long p )
@Override
public void putInt( int value )
{
putInt( offset, value );
long p = nextBoundedPointer( SIZE_OF_INT );
putIntAt( p, value );
offset += SIZE_OF_INT;
}

@Override
public void putInt( int offset, int value )
{
long p = getBoundedPointer( offset, SIZE_OF_INT );
putIntAt( p, value );
}

private void putIntAt( long p, int value )
{
if ( UnsafeUtil.allowUnalignedMemoryAccess )
{
UnsafeUtil.putInt( p, UnsafeUtil.storeByteOrderIsNative ? value : Integer.reverseBytes( value ) );
Expand Down Expand Up @@ -614,7 +657,8 @@ public void putBytes( byte[] data, int arrayOffset, int length )
@Override
public final short getShort()
{
short s = getShort( offset );
long p = nextBoundedPointer( SIZE_OF_SHORT );
short s = getShortAt( p );
offset += SIZE_OF_SHORT;
return s;
}
Expand All @@ -623,6 +667,11 @@ public final short getShort()
public short getShort( int offset )
{
long p = getBoundedPointer( offset, SIZE_OF_SHORT );
return getShortAt( p );
}

private short getShortAt( long p )
{
if ( UnsafeUtil.allowUnalignedMemoryAccess )
{
short x = UnsafeUtil.getShort( p );
Expand All @@ -641,14 +690,20 @@ private short getShortBigEndian( long p )
@Override
public void putShort( short value )
{
putShort( offset, value );
long p = nextBoundedPointer( SIZE_OF_SHORT );
putShortAt( p, value );
offset += SIZE_OF_SHORT;
}

@Override
public void putShort( int offset, short value )
{
long p = getBoundedPointer( offset, SIZE_OF_SHORT );
putShortAt( p, value );
}

private void putShortAt( long p, short value )
{
if ( UnsafeUtil.allowUnalignedMemoryAccess )
{
UnsafeUtil.putShort( p, UnsafeUtil.storeByteOrderIsNative ? value : Short.reverseBytes( value ) );
Expand Down
Expand Up @@ -57,6 +57,7 @@
import org.neo4j.graphdb.mockfs.DelegatingFileSystemAbstraction;
import org.neo4j.graphdb.mockfs.DelegatingStoreChannel;
import org.neo4j.graphdb.mockfs.EphemeralFileSystemAbstraction;
import org.neo4j.io.ByteUnit;
import org.neo4j.io.fs.FileSystemAbstraction;
import org.neo4j.io.fs.StoreChannel;
import org.neo4j.io.pagecache.impl.SingleFilePageSwapperFactory;
Expand Down Expand Up @@ -3713,18 +3714,18 @@ public void mustSupportUnalignedWordAccesses() throws Exception
// size of Huge Pages on Linux is 2 MB, but it can be configured to be
// as large as 1 GB - at least I have not heard of anyone trying to
// configure it to be more than that.
int pageSize = 1024 * 1024 * 8;
int pageSize = (int) ByteUnit.kibiBytes( 8 );
getPageCache( fs, 5, pageSize, PageCacheTracer.NULL, PageCursorTracerSupplier.NULL );

ThreadLocalRandom rng = ThreadLocalRandom.current();

try ( PagedFile pagedFile = pageCache.map( file( "a" ), filePageSize );
try ( PagedFile pagedFile = pageCache.map( file( "a" ), pageSize );
PageCursor cursor = pagedFile.io( 0, PF_SHARED_WRITE_LOCK ) )
{
assertTrue( cursor.next() );

long x = rng.nextLong();
int limit = pageSize - 8;
int limit = pageSize - Long.BYTES;
for ( int i = 0; i < limit; i++ )
{
x += i;
Expand All @@ -3733,6 +3734,7 @@ public void mustSupportUnalignedWordAccesses() throws Exception
cursor.setOffset( i );
long y = cursor.getLong();

assertFalse( "Should not have had a page out-of-bounds access!", cursor.checkAndClearBoundsFlag() );
if ( x != y )
{
String reason =
Expand Down

0 comments on commit a0abeff

Please sign in to comment.