Skip to content

Commit

Permalink
10x Faster GBPTreeLockTest
Browse files Browse the repository at this point in the history
By moving OtherThreadExecutor/Rule to common and using it
  • Loading branch information
tinwelint committed Jul 30, 2017
1 parent 5820b4f commit f885950
Show file tree
Hide file tree
Showing 5 changed files with 17 additions and 72 deletions.
Expand Up @@ -34,8 +34,6 @@
import java.util.concurrent.locks.LockSupport; import java.util.concurrent.locks.LockSupport;
import java.util.function.Predicate; import java.util.function.Predicate;


import org.neo4j.logging.Logger;

import static java.lang.String.format; import static java.lang.String.format;
import static java.lang.System.currentTimeMillis; import static java.lang.System.currentTimeMillis;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
Expand All @@ -48,7 +46,7 @@
* tests which handles two simultaneous transactions and interleave them, * tests which handles two simultaneous transactions and interleave them,
* f.ex for testing locking and data visibility. * f.ex for testing locking and data visibility.
* *
* @param <T> * @param <T> type of state
* @author Mattias Persson * @author Mattias Persson
*/ */
public class OtherThreadExecutor<T> implements ThreadFactory, Closeable public class OtherThreadExecutor<T> implements ThreadFactory, Closeable
Expand All @@ -59,7 +57,6 @@ public class OtherThreadExecutor<T> implements ThreadFactory, Closeable
private volatile ExecutionState executionState; private volatile ExecutionState executionState;
private final String name; private final String name;
private final long timeout; private final long timeout;
private Exception lastExecutionTrigger;


private static final class AnyThreadState implements Predicate<Thread> private static final class AnyThreadState implements Predicate<Thread>
{ {
Expand Down Expand Up @@ -130,7 +127,6 @@ public OtherThreadExecutor( String name, long timeout, TimeUnit unit, T initialS


public <R> Future<R> executeDontWait( final WorkerCommand<T, R> cmd ) public <R> Future<R> executeDontWait( final WorkerCommand<T, R> cmd )
{ {
lastExecutionTrigger = new Exception();
executionState = ExecutionState.REQUESTED_EXECUTION; executionState = ExecutionState.REQUESTED_EXECUTION;
return commandExecutor.submit( () -> return commandExecutor.submit( () ->
{ {
Expand Down Expand Up @@ -360,34 +356,6 @@ public void close()
} }
} }


public void dump( Logger logger )
{
logger.log( getClass().getName() + ", " + this + " state:" + state + " thread:" + thread +
" execution:" + executionState );
if ( thread != null )
{
logger.log( "Thread state:" + thread.getState() );
logger.log( "" );
for ( StackTraceElement element : thread.getStackTrace() )
{
logger.log( element.toString() );
}
}
else
{
logger.log( "No operations performed yet, so no thread" );
}
if ( lastExecutionTrigger != null )
{
logger.log( "" );
logger.log( "Last execution triggered from:" );
for ( StackTraceElement element : lastExecutionTrigger.getStackTrace() )
{
logger.log( element.toString() );
}
}
}

public void interrupt() public void interrupt()
{ {
if ( thread != null ) if ( thread != null )
Expand Down
Expand Up @@ -19,16 +19,15 @@
*/ */
package org.neo4j.index.internal.gbptree; package org.neo4j.index.internal.gbptree;


import org.junit.Rule;
import org.junit.Test; import org.junit.Test;


import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;


import org.neo4j.test.Race; import org.neo4j.test.Race;
import org.neo4j.test.rule.concurrent.OtherThreadRule;


import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotEquals;
Expand All @@ -45,9 +44,11 @@ public class GBPTreeLockTest
// State LU - locked | unlocked // State LU - locked | unlocked
// State LL - locked | locked // State LL - locked | locked


private GBPTreeLock lock = new GBPTreeLock(); private final GBPTreeLock lock = new GBPTreeLock();
private GBPTreeLock copy; private GBPTreeLock copy;
private final ExecutorService executor = Executors.newSingleThreadExecutor();
@Rule
public final OtherThreadRule<Void> executor = new OtherThreadRule<>();


@Test @Test
public void test_UU_UL_UU() throws Exception public void test_UU_UL_UU() throws Exception
Expand Down Expand Up @@ -238,35 +239,26 @@ private void assertThrow( Runnable unlock )
} }
} }


private void assertBlock( Runnable runLock, Runnable runUnlock ) throws ExecutionException, InterruptedException private void assertBlock( Runnable runLock, Runnable runUnlock ) throws Exception
{ {
Future<?> future = executor.submit( runLock ); Future<Object> future = executor.execute( state ->
shouldWait( future ); {
runLock.run();
return null;
} );
executor.get().waitUntilWaiting( details -> details.isAt( GBPTreeLock.class, "doLock" ) );
runUnlock.run(); runUnlock.run();
future.get(); future.get();
} }


private void shouldWait( Future<?> future )throws InterruptedException, ExecutionException
{
try
{
future.get( 200, TimeUnit.MILLISECONDS );
fail( "Expected timeout" );
}
catch ( TimeoutException e )
{
// good
}
}

private void assertUU() private void assertUU()
{ {
assertThrow( lock::writerUnlock ); assertThrow( lock::writerUnlock );
assertThrow( lock::cleanerUnlock ); assertThrow( lock::cleanerUnlock );
assertThrow( lock::writerAndCleanerUnlock ); assertThrow( lock::writerAndCleanerUnlock );
} }


private void assertUL() throws ExecutionException, InterruptedException private void assertUL() throws Exception
{ {
assertThrow( lock::writerUnlock ); assertThrow( lock::writerUnlock );
assertThrow( lock::writerAndCleanerUnlock ); assertThrow( lock::writerAndCleanerUnlock );
Expand All @@ -276,15 +268,15 @@ private void assertUL() throws ExecutionException, InterruptedException
assertBlock( copy::writerAndCleanerLock, copy::cleanerUnlock ); assertBlock( copy::writerAndCleanerLock, copy::cleanerUnlock );
} }


private void assertLU() throws ExecutionException, InterruptedException private void assertLU() throws Exception
{ {
assertThrow( lock::cleanerUnlock ); assertThrow( lock::cleanerUnlock );
assertThrow( lock::writerAndCleanerUnlock ); assertThrow( lock::writerAndCleanerUnlock );
copy = lock.copy(); copy = lock.copy();
assertBlock( copy::writerLock, copy::writerUnlock ); assertBlock( copy::writerLock, copy::writerUnlock );
} }


private void assertLL() throws ExecutionException, InterruptedException private void assertLL() throws Exception
{ {
copy = lock.copy(); copy = lock.copy();
assertBlock( copy::writerLock, copy::writerUnlock ); assertBlock( copy::writerLock, copy::writerUnlock );
Expand Down
Expand Up @@ -51,7 +51,6 @@ public File dumpState( Locks lm, LockWorker... workers ) throws IOException
{ {
// - what each is doing and have up to now // - what each is doing and have up to now
log.info( "Worker %s", worker ); log.info( "Worker %s", worker );
worker.dump( log.infoLogger() );
} }
return file; return file;
} }
Expand Down
Expand Up @@ -22,7 +22,6 @@
import java.util.concurrent.Future; import java.util.concurrent.Future;


import org.neo4j.kernel.DeadlockDetectedException; import org.neo4j.kernel.DeadlockDetectedException;
import org.neo4j.logging.Logger;
import org.neo4j.storageengine.api.lock.AcquireLockTimeoutException; import org.neo4j.storageengine.api.lock.AcquireLockTimeoutException;
import org.neo4j.test.OtherThreadExecutor; import org.neo4j.test.OtherThreadExecutor;


Expand Down Expand Up @@ -110,19 +109,6 @@ public boolean isLastGetLockDeadLock()
return state.deadlockOnLastWait; return state.deadlockOnLastWait;
} }


@Override
public void dump( Logger logger )
{
super.dump( logger );
logger.log( "What have I done up until now?" );
for ( String op : state.completedOperations )
{
logger.log( op );
}
logger.log( "Doing right now:" );
logger.log( state.doing == null ? "???" : state.doing );
}

private abstract static class AcquireLockCommand implements WorkerCommand<LockWorkerState, Void> private abstract static class AcquireLockCommand implements WorkerCommand<LockWorkerState, Void>
{ {
@Override @Override
Expand Down

0 comments on commit f885950

Please sign in to comment.