Skip to content

Commit

Permalink
Faster RelationshipGroupStoreIT
Browse files Browse the repository at this point in the history
by only creating necessary amount of reltypes.
also added a unit test for the same issue.
  • Loading branch information
tinwelint committed Sep 19, 2016
1 parent 3523d11 commit 99b9ba1
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 29 deletions.
Expand Up @@ -21,70 +21,67 @@


import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.RuleChain;

import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node; import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.RelationshipType; import org.neo4j.graphdb.RelationshipType;
import org.neo4j.graphdb.Transaction; import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.factory.GraphDatabaseFactory; import org.neo4j.graphdb.factory.GraphDatabaseBuilder;
import org.neo4j.graphdb.factory.GraphDatabaseSettings; import org.neo4j.graphdb.factory.GraphDatabaseSettings;
import org.neo4j.kernel.impl.storageengine.impl.recordstorage.RecordStorageEngine; import org.neo4j.kernel.impl.storageengine.impl.recordstorage.RecordStorageEngine;
import org.neo4j.kernel.internal.GraphDatabaseAPI; import org.neo4j.kernel.internal.GraphDatabaseAPI;
import org.neo4j.test.rule.CleanupRule; import org.neo4j.test.rule.DatabaseRule;
import org.neo4j.test.rule.TestDirectory; import org.neo4j.test.rule.ImpermanentDatabaseRule;

import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.neo4j.helpers.collection.Iterables.count; import static org.neo4j.helpers.collection.Iterables.count;


public class RelationshipGroupStoreIT public class RelationshipGroupStoreIT
{ {
private final TestDirectory directory = TestDirectory.testDirectory(); private static final int RELATIONSHIP_COUNT = 20;
private final CleanupRule cleanupRule = new CleanupRule();


@Rule @Rule
public RuleChain ruleChain = RuleChain.outerRule( directory ).around( cleanupRule ); public final DatabaseRule db = new ImpermanentDatabaseRule()
{
@Override
protected void configure( GraphDatabaseBuilder builder )
{
builder.setConfig( GraphDatabaseSettings.dense_node_threshold, "1" );
}
};


@Test @Test
public void shouldCreateAllTheseRelationshipTypes() throws Exception public void shouldCreateAllTheseRelationshipTypes() throws Exception
{ {
GraphDatabaseService db = new GraphDatabaseFactory() shiftHighId( db );
.newEmbeddedDatabaseBuilder( directory.graphDbDir() )
.setConfig( GraphDatabaseSettings.dense_node_threshold, "1" )
.newGraphDatabase();
cleanupRule.add( db );

shiftHighId( (GraphDatabaseAPI) db );


Node node;
try ( Transaction tx = db.beginTx() ) try ( Transaction tx = db.beginTx() )
{ {
Node node = db.createNode(); node = db.createNode();
for ( int i = 0; i < 5_000; i++ ) for ( int i = 0; i < RELATIONSHIP_COUNT; i++ )
{ {
node.createRelationshipTo( db.createNode(), type( i + 1 ) ); node.createRelationshipTo( db.createNode(), type( i ) );
} }
tx.success(); tx.success();
} }


int nodeWithHighRelationshipTypeID = 4001;
try ( Transaction ignored = db.beginTx() ) try ( Transaction ignored = db.beginTx() )
{ {
Node node = db.getNodeById( 0 ); for ( int i = 0; i < RELATIONSHIP_COUNT; i++ )
assertEquals( "Should be possible to get relationships of type with id in unsigned short range.", {
1, count( node.getRelationships( type( nodeWithHighRelationshipTypeID ) ) ) ); assertEquals( "Should be possible to get relationships of type with id in unsigned short range.",
1, count( node.getRelationships( type( i ) ) ) );
}
} }
} }


private void shiftHighId( GraphDatabaseAPI db ) private void shiftHighId( GraphDatabaseAPI db )
{ {
RecordStorageEngine storageEngine = db.getDependencyResolver().resolveDependency( RecordStorageEngine.class ); RecordStorageEngine storageEngine = db.getDependencyResolver().resolveDependency( RecordStorageEngine.class );
NeoStores neoStores = storageEngine.testAccessNeoStores(); NeoStores neoStores = storageEngine.testAccessNeoStores();
neoStores.getRelationshipTypeTokenStore().setHighId( 30000 ); neoStores.getRelationshipTypeTokenStore().setHighId( Short.MAX_VALUE - RELATIONSHIP_COUNT / 2 );
} }


private RelationshipType type( int i ) private RelationshipType type( int i )
{ {
return RelationshipType.withName( "TYPE_" + i ); return RelationshipType.withName( "TYPE_" + i );
} }

} }
@@ -0,0 +1,82 @@
/*
* 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.kernel.impl.store.format.standard;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

import java.util.Collection;

import org.neo4j.io.pagecache.PageCursor;
import org.neo4j.io.pagecache.StubPageCursor;
import org.neo4j.kernel.impl.store.format.RecordFormat;
import org.neo4j.kernel.impl.store.format.RecordFormats;
import org.neo4j.kernel.impl.store.record.RelationshipGroupRecord;

import static org.junit.Assert.assertEquals;
import static java.util.Arrays.asList;

import static org.neo4j.kernel.impl.store.NoStoreHeader.NO_STORE_HEADER;
import static org.neo4j.kernel.impl.store.record.RecordLoad.NORMAL;

@RunWith( Parameterized.class )
public class RelationshipGroupRecordFormatTest
{
@Parameters
public static Collection<RecordFormats> formats()
{
return asList( StandardV2_1.RECORD_FORMATS, StandardV2_2.RECORD_FORMATS, StandardV2_3.RECORD_FORMATS,
StandardV3_0.RECORD_FORMATS );
}

private final RecordFormat<RelationshipGroupRecord> format;
private final int recordSize;

public RelationshipGroupRecordFormatTest( RecordFormats formats )
{
this.format = formats.relationshipGroup();
this.recordSize = format.getRecordSize( NO_STORE_HEADER );
}

@Test
public void shouldReadUnsignedRelationshipTypeId() throws Exception
{
// GIVEN
try ( PageCursor cursor = new StubPageCursor( 1, recordSize * 10 ) )
{
int offset = 10;
cursor.next();
RelationshipGroupRecord group = new RelationshipGroupRecord( 2 )
.initialize( true, Short.MAX_VALUE + offset, 1, 2, 3, 4, 5 );
cursor.setOffset( offset );
format.write( group, cursor, recordSize );

// WHEN
RelationshipGroupRecord read = new RelationshipGroupRecord( group.getId() );
cursor.setOffset( offset );
format.read( read, cursor, NORMAL, recordSize );

// THEN
assertEquals( group, read );
}
}
}
Expand Up @@ -31,7 +31,6 @@
import java.io.IOException; import java.io.IOException;
import java.util.BitSet; import java.util.BitSet;
import java.util.Collection; import java.util.Collection;

import org.neo4j.io.fs.DefaultFileSystemAbstraction; import org.neo4j.io.fs.DefaultFileSystemAbstraction;
import org.neo4j.kernel.configuration.Config; import org.neo4j.kernel.configuration.Config;
import org.neo4j.kernel.impl.logging.NullLogService; import org.neo4j.kernel.impl.logging.NullLogService;
Expand Down Expand Up @@ -186,15 +185,15 @@ public void shouldDefragmentRelationshipGroupsWhenSomeDense() throws Exception
verifyGroupsAreSequentiallyOrderedByNode(); verifyGroupsAreSequentiallyOrderedByNode();
} }


private void defrag( long nodeCount, RecordStore<RelationshipGroupRecord> groupStore ) private void defrag( int nodeCount, RecordStore<RelationshipGroupRecord> groupStore )
{ {
Monitor monitor = mock( Monitor.class ); Monitor monitor = mock( Monitor.class );
RelationshipGroupDefragmenter defragmenter = new RelationshipGroupDefragmenter( CONFIG, RelationshipGroupDefragmenter defragmenter = new RelationshipGroupDefragmenter( CONFIG,
ExecutionMonitors.invisible(), monitor ); ExecutionMonitors.invisible(), monitor );


// Calculation below correlates somewhat to calculation in RelationshipGroupDefragmenter. // Calculation below correlates somewhat to calculation in RelationshipGroupDefragmenter.
// Anyway we verify below that we exercise the multi-pass bit, which is what we want // Anyway we verify below that we exercise the multi-pass bit, which is what we want
long memory = groupStore.getHighId() * 8 + 200; long memory = groupStore.getHighId() * 15 + 200;
defragmenter.run( memory, stores, nodeCount ); defragmenter.run( memory, stores, nodeCount );


// Verify that we exercise the multi-pass functionality // Verify that we exercise the multi-pass functionality
Expand Down
@@ -1,3 +1,22 @@
/*
* 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 Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.kernel.ha.management; package org.neo4j.kernel.ha.management;


import org.junit.Before; import org.junit.Before;
Expand Down

0 comments on commit 99b9ba1

Please sign in to comment.