/*
* Written by Gil Tene and Martin Thompson, and released to the public domain,
* as explained at http://creativecommons.org/publicdomain/zero/1.0/
*/
package org.ObjectLayoutApiTests;
import org.ObjectLayout.ConstructionContext;
import org.ObjectLayout.CtorAndArgs;
import org.ObjectLayout.CtorAndArgsProvider;
import org.ObjectLayout.StructuredArray;
import org.junit.Test;
import java.lang.reflect.Constructor;
import java.util.Random;
import static java.lang.Long.valueOf;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
public class StructuredArrayPerfTest {
StructuredArray<MockStructure> array;
StructuredArrayOfMockStructure subclassedArray;
GenericEncapsulatedArray<MockStructure> genericEncapsulatedArray;
EncapsulatedArray encapsulatedArray;
EncapsulatedRandomizedArray encapsulatedRandomizedArray;
class EncapsulatedArray {
final MockStructure[] array;
EncapsulatedArray(int length) {
array = new MockStructure[length];
for (int i = 0; i < array.length; i++) {
array[i] = new MockStructure(i, i*2);
}
}
MockStructure get(final int index) {
return array[index];
}
int getLength() {
return array.length;
}
}
class EncapsulatedRandomizedArray {
final MockStructure[] array;
EncapsulatedRandomizedArray(int length) {
array = new MockStructure[length];
for (int i = 0; i < array.length; i++) {
array[i] = new MockStructure(i, i*2);
}
// swap elements around randomly
Random generator = new Random();
for (int i = 0; i < array.length; i++) {
int target = generator.nextInt(array.length);
MockStructure temp = array[target];
array[target] = array[i];
array[i] = temp;
}
}
MockStructure get(final int index) {
return array[index];
}
int getLength() {
return array.length;
}
}
class GenericEncapsulatedArray<E> {
final E[] array;
GenericEncapsulatedArray(Constructor<E> constructor, int length) {
@SuppressWarnings("unchecked")
final E[] a = (E[]) new Object[length];
array = a;
try {
for (int i = 0; i < array.length; i++) {
array[i] = constructor.newInstance(i, i * 2);
}
} catch (final Exception ex) {
throw new RuntimeException(ex);
}
}
E get(final int index) {
return array[index];
}
int getLength() {
return array.length;
}
}
long arrayLoopSumTest() {
long sum = 0;
for (int i = 0 ; i < array.getLength(); i++) {
sum += array.get(i).getTestValue();
}
return sum;
}
long subclassedArrayLoopSumTest() {
long sum = 0;
for (int i = 0 ; i < array.getLength(); i++) {
sum += subclassedArray.get(i).getTestValue();
}
return sum;
}
long loopGenericEncapsulatedArraySumTest() {
long sum = 0;
for (int i = 0 ; i < genericEncapsulatedArray.getLength(); i++) {
sum += genericEncapsulatedArray.get(i).getTestValue();
}
return sum;
}
long loopEncapsulatedArraySumTest() {
long sum = 0;
for (int i = 0 ; i < encapsulatedArray.getLength(); i++) {
sum += encapsulatedArray.get(i).getTestValue();
}
return sum;
}
long loopEncapsulatedRandomizedArraySumTest() {
long sum = 0;
for (int i = 0 ; i < encapsulatedRandomizedArray.getLength(); i++) {
sum += encapsulatedRandomizedArray.get(i).getTestValue();
}
return sum;
}
public void testLoop(int length) {
long startTime5 = System.nanoTime();
long sum5 = loopEncapsulatedRandomizedArraySumTest();
long endTime5 = System.nanoTime();
double loopsPerSec5 = 1000 * (double) length / (endTime5 - startTime5);
long startTime4 = System.nanoTime();
long sum4 = loopEncapsulatedArraySumTest();
long endTime4 = System.nanoTime();
double loopsPerSec4 = 1000 * (double) length / (endTime4 - startTime4);
long startTime3 = System.nanoTime();
long sum3 = loopGenericEncapsulatedArraySumTest();
long endTime3 = System.nanoTime();
double loopsPerSec3 = 1000 * (double) length / (endTime3 - startTime3);
long startTime2 = System.nanoTime();
long sum2 = subclassedArrayLoopSumTest();
long endTime2 = System.nanoTime();
double loopsPerSec2 = 1000 * (double) length / (endTime2 - startTime2);
long startTime1 = System.nanoTime();
long sum1 = arrayLoopSumTest();
long endTime1 = System.nanoTime();
double loopsPerSec1 = 1000 * (double) length / (endTime1 - startTime1);
System.out.println("StructuredArray: (" + loopsPerSec1 +
"M), SubclassedSA: (" + loopsPerSec2 +
"M), GenericEncapsulatedArray: (" + loopsPerSec3 +
"M), EncapsulatedArray: (" + loopsPerSec4 +
"M), EncapsulatedRandomizedArray: (" + loopsPerSec5 +
"M) cksum = " + (sum1 + sum2 + sum3 + sum4 + sum5));
}
@Test
public void testLoopingSpeeds() throws NoSuchMethodException {
final int length = 1000000;
final Object[] args = new Object[2];
final CtorAndArgs<MockStructure> ctorAndArgs =
new CtorAndArgs<MockStructure>(
MockStructure.class.getConstructor(MockStructure.constructorArgTypes), args);
final CtorAndArgsProvider<MockStructure> ctorAndArgsProvider =
new CtorAndArgsProvider<MockStructure>() {
@Override
public CtorAndArgs<MockStructure> getForContext(
ConstructionContext<MockStructure> context) throws NoSuchMethodException {
args[0] = context.getIndex();
args[1] = context.getIndex() * 2;
return ctorAndArgs;
}
};
array = StructuredArray.newInstance(MockStructure.class, ctorAndArgsProvider, length);
subclassedArray = StructuredArrayOfMockStructure.newInstance(ctorAndArgsProvider, length);
encapsulatedArray = new EncapsulatedArray(length);
encapsulatedRandomizedArray = new EncapsulatedRandomizedArray(length);
genericEncapsulatedArray =
new GenericEncapsulatedArray<MockStructure>(
MockStructure.class.getConstructor(MockStructure.constructorArgTypes), length);
for (int i = 0; i < 10; i++) {
testLoop(length);
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
}
}
}
public static void main(String[] args) {
try {
StructuredArrayPerfTest test = new StructuredArrayPerfTest();
// Useful for keeping program alive and active when doing drill-down browsing in an interactive profiler:
while (true) {
test.testLoopingSpeeds();
}
} catch (Exception ex) {
}
}
///////////////////////////////////////////////////////////////////////////////////////////////
// Test support below
///////////////////////////////////////////////////////////////////////////////////////////////
public static class MockStructure {
static final Class[] constructorArgTypes = {Long.TYPE, Long.TYPE};
private long index = -1;
private long testValue = Long.MIN_VALUE;
public MockStructure() {
}
public MockStructure(final long index, final long testValue) {
this.index = index;
this.testValue = testValue;
}
public MockStructure(MockStructure src) {
this.index = src.index;
this.testValue = src.testValue;
}
public long getIndex() {
return index;
}
public void setIndex(final long index) {
this.index = index;
}
public long getTestValue() {
return testValue;
}
public void setTestValue(final long testValue) {
this.testValue = testValue;
}
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final MockStructure that = (MockStructure)o;
return index == that.index && testValue == that.testValue;
}
public int hashCode() {
int result = (int)(index ^ (index >>> 32));
result = 31 * result + (int)(testValue ^ (testValue >>> 32));
return result;
}
public String toString() {
return "MockStructure{" +
"index=" + index +
", testValue=" + testValue +
'}';
}
}
public static class MockStructureWithFinalField {
private final int value = 888;
}
public static class StructuredArrayOfMockStructure extends StructuredArray<MockStructure> {
public static StructuredArrayOfMockStructure newInstance(
final CtorAndArgsProvider<MockStructure> ctorAndArgsProvider,final long length) {
return StructuredArray.newInstance(
StructuredArrayOfMockStructure.class, MockStructure.class, length, ctorAndArgsProvider);
}
}
}