Skip to content

Commit

Permalink
NodeRelationshipCache has 6B ID support
Browse files Browse the repository at this point in the history
since new enterprise format requires it. For this a new ByteArray
had to be implemented. ByteArray is just like IntArray/LongArray an
abstraction of a primitive array which can grow dynamically and live
partly on- as well as off-heap, where ever there's available space.

A semi-internal accessor for getting to the most "raw" array instance
for a particular ID and making all calls about that ID on that instance
has been added as well (NumberArray#at(index)).
This makes performance better and so the net performance difference
is still positive compared to using a LongArray.
  • Loading branch information
tinwelint committed Mar 29, 2016
1 parent 4e1a939 commit ca27374
Show file tree
Hide file tree
Showing 25 changed files with 1,386 additions and 352 deletions.
@@ -0,0 +1,56 @@
/*
* Copyright (c) 2002-2016 "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.unsafe.impl.batchimport.cache;

/**
* Contains basic functionality of fixed size number arrays.
*/
abstract class BaseNumberArray<N extends NumberArray<N>> implements NumberArray<N>
{
protected final int itemSize;
private final long base;

/**
* @param itemSize byte size of each item in this array.
* @param base base index to rebase all indexes in accessor methods off of. See {@link #at(long)}.
*/
protected BaseNumberArray( int itemSize, long base )
{
this.itemSize = itemSize;
this.base = base;
}

@SuppressWarnings( "unchecked" )
@Override
public N at( long index )
{
return (N)this;
}

/**
* Utility for rebasing an external index to internal index.
* @param index external index.
* @return index into internal data structure.
*/
protected long rebase( long index )
{
return index - base;
}
}
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2002-2016 "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.unsafe.impl.batchimport.cache;

/**
* Abstraction of a {@code byte[]} so that different implementations can be plugged in, for example
* off-heap, dynamically growing, or other implementations. This interface is slightly different than
* {@link IntArray} and {@link LongArray} in that one item in the array isn't necessarily just a byte,
* instead item size can be set to any number and the bytes in an item can be read and written as other
* number representations like {@link #setInt(long, int, int) int} or {@link #setLong(long, int, long) long},
* even a special {@link #set6BLong(long, int, long) 6B long}. More can easily be added on demand.
*
* @see NumberArrayFactory
*/
public interface ByteArray extends NumberArray<ByteArray>
{
void get( long index, byte[] into );

byte getByte( long index, int offset );

short getShort( long index, int offset );

int getInt( long index, int offset );

long get6BLong( long index, int offset );

long getLong( long index, int offset );

void set( long index, byte[] value );

void setByte( long index, int offset, byte value );

void setShort( long index, int offset, short value );

void setInt( long index, int offset, int value );

void set6BLong( long index, int offset, long value );

void setLong( long index, int offset, long value );
}

This file was deleted.

@@ -0,0 +1,144 @@
/*
* Copyright (c) 2002-2016 "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.unsafe.impl.batchimport.cache;

import java.nio.ByteBuffer;

import static org.neo4j.unsafe.impl.batchimport.cache.HeapByteArray.get6BLongFromByteBuffer;

public class DynamicByteArray extends DynamicNumberArray<ByteArray> implements ByteArray
{
private final byte[] defaultValue;
private final ByteBuffer defaultValueConvenienceBuffer;

public DynamicByteArray( NumberArrayFactory factory, long chunkSize, byte[] defaultValue )
{
super( factory, chunkSize, new ByteArray[0] );
this.defaultValue = defaultValue;
this.defaultValueConvenienceBuffer = ByteBuffer.wrap( defaultValue );
}

@Override
public void swap( long fromIndex, long toIndex, int numberOfEntries )
{
// Let's just do this the stupid way. There's room for optimization here
byte[] intermediary = defaultValue.clone();
byte[] transport = defaultValue.clone();
for ( int i = 0; i < numberOfEntries; i++ )
{
get( fromIndex+i, intermediary );
get( toIndex+i, transport );
set( fromIndex+i, transport );
set( toIndex+i, intermediary );
}
}

@Override
public void get( long index, byte[] into )
{
ByteArray chunk = chunkOrNullAt( index );
if ( chunk != null )
{
chunk.get( index, into );
}
else
{
System.arraycopy( defaultValue, 0, into, 0, defaultValue.length );
}
}

@Override
public byte getByte( long index, int offset )
{
ByteArray chunk = chunkOrNullAt( index );
return chunk != null ? chunk.getByte( index, offset ) : defaultValueConvenienceBuffer.get( offset );
}

@Override
public short getShort( long index, int offset )
{
ByteArray chunk = chunkOrNullAt( index );
return chunk != null ? chunk.getShort( index, offset ) : defaultValueConvenienceBuffer.getShort( offset );
}

@Override
public int getInt( long index, int offset )
{
ByteArray chunk = chunkOrNullAt( index );
return chunk != null ? chunk.getInt( index, offset ) : defaultValueConvenienceBuffer.getInt( offset );
}

@Override
public long get6BLong( long index, int offset )
{
ByteArray chunk = chunkOrNullAt( index );
return chunk != null ? chunk.get6BLong( index, offset ) :
get6BLongFromByteBuffer( defaultValueConvenienceBuffer, offset );
}

@Override
public long getLong( long index, int offset )
{
ByteArray chunk = chunkOrNullAt( index );
return chunk != null ? chunk.getLong( index, offset ) : defaultValueConvenienceBuffer.getLong( offset );
}

@Override
public void set( long index, byte[] value )
{
at( index ).set( index, value );
}

@Override
public void setByte( long index, int offset, byte value )
{
at( index ).setByte( index, offset, value );
}

@Override
public void setShort( long index, int offset, short value )
{
at( index ).setShort( index, offset, value );
}

@Override
public void setInt( long index, int offset, int value )
{
at( index ).setInt( index, offset, value );
}

@Override
public void set6BLong( long index, int offset, long value )
{
at( index ).set6BLong( index, offset, value );
}

@Override
public void setLong( long index, int offset, long value )
{
at( index ).setLong( index, offset, value );
}

@Override
protected ByteArray addChunk( long chunkSize, long base )
{
return factory.newByteArray( chunkSize, defaultValue, base );
}
}
Expand Up @@ -31,21 +31,21 @@ public class DynamicIntArray extends DynamicNumberArray<IntArray> implements Int

public DynamicIntArray( NumberArrayFactory factory, long chunkSize, int defaultValue )
{
super( factory, chunkSize );
super( factory, chunkSize, new IntArray[0] );
this.defaultValue = defaultValue;
}

@Override
public int get( long index )
{
IntArray chunk = chunkOrNullAt( index );
return chunk != null ? chunk.get( index( index ) ) : defaultValue;
return chunk != null ? chunk.get( index ) : defaultValue;
}

@Override
public void set( long index, int value )
{
ensureChunkAt( index ).set( index( index ), value );
at( index ).set( index, value );
}

@Override
Expand All @@ -61,8 +61,8 @@ public void swap( long fromIndex, long toIndex, int numberOfEntries )
}

@Override
protected IntArray addChunk( long chunkSize )
protected IntArray addChunk( long chunkSize, long base )
{
return factory.newIntArray( chunkSize, defaultValue );
return factory.newIntArray( chunkSize, defaultValue, base );
}
}

0 comments on commit ca27374

Please sign in to comment.