/**
* Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.engine.depgraph;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertSame;
import static org.testng.Assert.assertTrue;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.util.test.TestGroup;
/**
* Tests the {@link RunQueue} implementations
*/
@Test(groups = TestGroup.UNIT)
public class RunQueueTest {
private ExecutorService _executor;
@BeforeClass
public void init() {
_executor = Executors.newCachedThreadPool();
}
@AfterClass
public void done() {
_executor.shutdownNow();
_executor = null;
}
private ContextRunnable runnable() {
return new ContextRunnable() {
@Override
public boolean tryRun(final GraphBuildingContext context) {
// No-op
return true;
}
};
}
private void testSpeed(final RunQueue queue, final CyclicBarrier barrier, final double[] speed) {
try {
int isEmpty = 0, take = 0, add = 0;
long time = 0;
for (int j = 0; j < 2; j++) {
barrier.await();
final long start = System.nanoTime();
isEmpty = 0;
take = 0;
add = 0;
do {
isEmpty++;
if (!queue.isEmpty()) {
take++;
final ContextRunnable runnable = queue.take();
if (runnable != null) {
add++;
queue.add(runnable);
}
}
time = System.nanoTime() - start;
} while (time < 5000000000L);
}
synchronized (speed) {
speed[0] += (double) isEmpty / ((double) time / 1e9);
speed[1] += (double) take / ((double) time / 1e9);
speed[2] += (double) add / ((double) time / 1e9);
}
barrier.await();
} catch (InterruptedException e) {
throw new OpenGammaRuntimeException("Interrupted", e);
} catch (BrokenBarrierException e) {
throw new OpenGammaRuntimeException("Broken barrier", e);
}
}
@SuppressWarnings("unused")
private void testSpeed(final RunQueue queue, final int threads) {
final double[] speed = new double[3];
final CyclicBarrier barrier = new CyclicBarrier(threads);
for (int i = 1; i < threads; i++) {
_executor.submit(new Runnable() {
@Override
public void run() {
testSpeed(queue, barrier, speed);
}
});
}
for (int i = 0; i < 100; i++) {
queue.add(runnable());
}
testSpeed(queue, barrier, speed);
System.out.println(queue + ", " + threads + ", " + speed[0] + ", " + speed[1] + ", " + speed[2]);
}
private void testSpeed(final RunQueueFactory queueFactory) {
/*testSpeed(queueFactory.createRunQueue(), 1);
testSpeed(queueFactory.createRunQueue(), 4);
testSpeed(queueFactory.createRunQueue(), 8);
testSpeed(queueFactory.createRunQueue(), 16);*/
}
private void testLIFO(final RunQueueFactory queueFactory) {
final RunQueue queue = queueFactory.createRunQueue();
assertTrue(queue.isEmpty());
assertEquals(queue.size(), 0);
final ContextRunnable r1 = runnable();
final ContextRunnable r2 = runnable();
final ContextRunnable r3 = runnable();
queue.add(r1);
assertFalse(queue.isEmpty());
queue.add(r2);
queue.add(r3);
assertEquals(queue.size(), 3);
assertSame(queue.take(), r3);
assertSame(queue.take(), r2);
assertEquals(queue.size(), 1);
queue.add(r2);
queue.add(r3);
assertEquals(queue.size(), 3);
assertSame(queue.take(), r3);
assertSame(queue.take(), r2);
assertSame(queue.take(), r1);
assertEquals(queue.size(), 0);
assertTrue(queue.isEmpty());
}
private void testFIFO(final RunQueueFactory queueFactory) {
final RunQueue queue = queueFactory.createRunQueue();
assertTrue(queue.isEmpty());
assertEquals(queue.size(), 0);
final ContextRunnable r1 = runnable();
final ContextRunnable r2 = runnable();
final ContextRunnable r3 = runnable();
queue.add(r1);
assertFalse(queue.isEmpty());
queue.add(r2);
queue.add(r3);
assertEquals(queue.size(), 3);
assertSame(queue.take(), r1);
assertSame(queue.take(), r2);
assertEquals(queue.size(), 1);
queue.add(r1);
queue.add(r2);
assertEquals(queue.size(), 3);
assertSame(queue.take(), r3);
assertSame(queue.take(), r1);
assertSame(queue.take(), r2);
assertEquals(queue.size(), 0);
assertTrue(queue.isEmpty());
}
public void testLinkedListLIFO() {
testSpeed(RunQueueFactory.getLifoLinkedList());
testLIFO(RunQueueFactory.getLifoLinkedList());
}
public void testLinkedListFIFO() {
testSpeed(RunQueueFactory.getFifoLinkedList());
testFIFO(RunQueueFactory.getFifoLinkedList());
}
public void testConcurrentLinkedQueue() {
testSpeed(RunQueueFactory.getConcurrentLinkedQueue());
testFIFO(RunQueueFactory.getConcurrentLinkedQueue());
}
public void testStackRunQueue() {
testSpeed(RunQueueFactory.getConcurrentStack());
testLIFO(RunQueueFactory.getConcurrentStack());
}
public void testOrderedRunQueue() {
testSpeed(RunQueueFactory.getOrdered());
testLIFO(RunQueueFactory.getOrdered());
}
}