package uk.ac.uea.threadr.threadrtest;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.logging.Level;
import uk.ac.uea.threadr.AbstractReturnType;
import uk.ac.uea.threadr.ParallelTask;
import uk.ac.uea.threadr.PostSequentialHandler;
import uk.ac.uea.threadr.Threadr;
import uk.ac.uea.threadr.ThreadrResult;
import uk.ac.uea.threadr.internal.MemoryMonitor;
import uk.ac.uea.threadr.internal.MemoryMonitor.MemoryUnits;
public class ThreadrTest implements ParallelTask, Serializable {
private static final long serialVersionUID = 5003801644304239806L;
private int[] values = null;
public static int SIZE = 50000;
public static volatile int TASK_COUNT = 2;
public static volatile int REPS = 1;
private static final Random random = new Random();
public static void main(String[] args) {
if (args.length == 2) {
TASK_COUNT = Integer.parseInt(args[0]);
REPS = Integer.parseInt(args[1]);
}
/* Set up Threadr. */
Threadr threadr = new Threadr();
threadr.enableLogging();
threadr.setOutputLevel(Level.FINEST);
threadr.setSequentialHandler(new PostSequentialHandler());
for (int i = 1; i <= TASK_COUNT; i++) {
MemoryMonitor monitor = MemoryMonitor.getInstance();
List<Long> seqs = new ArrayList<>();
List<Long> pars = new ArrayList<>();
List<Long> thrs = new ArrayList<>();
List<Float> impsPar = new ArrayList<>();
List<Float> impsThr = new ArrayList<>();
List<Double> seqMemUse = new ArrayList<>();
List<Double> thrMemUse = new ArrayList<>();
List<Double> parMemUse = new ArrayList<>();
ThreadrTest[] test = new ThreadrTest[i];
for (int j = 0; j < i; j++) {
test[j] = new ThreadrTest();
}
Test2[] test2 = new Test2[i];
for (int j = 0; j < i; j++) {
test2[j] = new Test2();
}
ThreadrTest[] test3 = new ThreadrTest[i];
for (int j = 0; j < i; j++) {
test3[j] = new ThreadrTest();
}
/* Save the generated tests. */
saveTest("test1", test);
saveTest("test2", test2);
saveTest("test3", test3);
System.out.println("\n------------------------------");
System.out.printf("Test number - %d;\n", i);
System.out.printf("Repetitions - %d;\n", REPS);
System.out.printf("Tasks per test - %d;\n", i);
for (int j = 0; j < REPS;) {
/* Load the saved state of the parallelism test. */
test = (ThreadrTest[]) loadTests("test1");
/* Load the saved state of the threading test. */
test2 = (Test2[]) loadTests("test2");
/* Load the saved state of the sequential test. */
test3 = (ThreadrTest[]) loadTests("test3");
long startTime, endTime, diff1, diff2, diff3;
/* Start the memory monitor. */
Thread monitorThread = new Thread(monitor);
monitorThread.start();
System.gc();
/* Run the sequential tests. */
startTime = System.currentTimeMillis();
for (ThreadrTest t : test3) {
Threadr.logger.finer(t.toString());
AbstractReturnType<?> result = t.call();
Threadr.logger.finer(result.toString());
}
endTime = System.currentTimeMillis();
/* Stop the memory monitor. */
try {
monitorThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
seqMemUse.add(monitor.getMaxUsedMemory(MemoryUnits.MEGABYTE));
diff1 = endTime - startTime;
seqs.add(diff1);
Threadr.logger.fine(String.format(
"\tNon-threaded tasks execution time %dms\n", diff1));
/* Test parallel executions. */
System.gc();
threadr.reset();
threadr.addTasks(test);
for (ThreadrTest t : test) {
Threadr.logger.finer(t.toString());
}
startTime = System.currentTimeMillis();
ThreadrResult results = threadr.execute();
endTime = System.currentTimeMillis();
diff2 = endTime - startTime;
pars.add(diff2);
double totalMem = threadr.getMemoryMonitor().getMaxUsedMemory(MemoryUnits.MEGABYTE);
/* Get all the MemoryMonitors out from the results. */
for (AbstractReturnType<?> result : results.getResults()) {
/*
* If the monitors are different, we must be looking at
* another VM.
*/
MemoryMonitor resultMon = (MemoryMonitor) result.getResult();
if (!result.getResult().equals(threadr.getMemoryMonitor())) {
totalMem += resultMon.getMaxUsedMemory(MemoryUnits.MEGABYTE);
}
}
parMemUse.add(totalMem);
Threadr.logger
.fine(String
.format("\nVirtual Machine tasks execution time %dms\n",
diff2));
for (AbstractReturnType<?> result : results.getResults()) {
Threadr.logger.finer(result.toString());
}
/* Work out the percentage increase in execution speed. */
float percentage = (((float) (diff1 - diff2) / (float) diff1) * 100.0f);
impsPar.add(percentage);
Threadr.logger.fine(String.format(
"\tImprovement: %03.02f%% \n", percentage));
/* Set up and test threaded executions. */
System.gc();
threadr.reset();
threadr.addTasks(test2);
for (Test2 t : test2) {
Threadr.logger.finer(t.toString());
}
startTime = System.currentTimeMillis();
results = threadr.execute();
endTime = System.currentTimeMillis();
diff3 = endTime - startTime;
thrs.add(diff3);
totalMem = threadr.getMemoryMonitor().getMaxUsedMemory(MemoryUnits.MEGABYTE);
for (AbstractReturnType<?> result : results.getResults()) {
MemoryMonitor resultMon = (MemoryMonitor) result
.getResult();
if (!result.getResult().equals(threadr.getMemoryMonitor())) {
totalMem += resultMon.getMaxUsedMemory(MemoryUnits.MEGABYTE);
}
}
thrMemUse.add(totalMem);
Threadr.logger.fine(String.format(
"\tThreaded tasks execution time %dms\n", diff2));
for (AbstractReturnType<?> result : results.getResults()) {
Threadr.logger.finer(result.toString());
}
/* Work out the percentage increase in execution speed. */
percentage = (((float) (diff1 - diff3) / (float) diff1) * 100.0f);
impsThr.add(percentage);
Threadr.logger.fine(String.format(
"\tImprovement: %03.02f%% \n", percentage));
Threadr.logger.info(String.format(
"Test %d - %3.2f%% complete\n", i,
((float) ++j / (float) REPS) * 100.0f));
}
/* List all the execution times for sequential executions. */
StringBuffer resultStr = new StringBuffer(
"\nSequential Times (ms); ");
for (Long t : seqs) {
resultStr.append(String.format("%d, ", t));
}
/* List all the execution times for parallel executions. */
resultStr.append("\nParallel Times (ms); ");
for (Long t : pars) {
resultStr.append(String.format("%d, ", t));
}
/* List the execution time improvements. */
resultStr.append("\nResult Improvements (%); ");
for (Float f : impsPar) {
resultStr.append(String.format("%3.2f, ", f));
}
/* List all the execution times for threaded executions. */
resultStr.append("\nThreaded Times (ms); ");
for (Long t : thrs) {
resultStr.append(String.format("%d, ", t));
}
resultStr.append("\nResult Improvements (%); ");
for (Float f : impsThr) {
resultStr.append(String.format("%3.2f, ", f));
}
/* Add the used memory data. */
resultStr.append("\nMemory Usage (MB);");
resultStr.append("\nSequential Used; ");
for (Double l : seqMemUse) {
resultStr.append(String.format("%3.2f, ", l));
}
resultStr.append("\nParallel Used; ");
for (Double l : parMemUse) {
resultStr.append(String.format("%3.2f, ", l));
}
resultStr.append("\nThreaded Used; ");
for (Double l : thrMemUse) {
resultStr.append(String.format("%3.2f, ", l));
}
System.out.println(resultStr.toString());
}
}
public ThreadrTest() {
values = new int[SIZE];
for (int i = 0; i < SIZE; i++) {
values[i] = random.nextInt(1000000);
}
}
@Override
public AbstractReturnType<?> call() {
MemoryReturnType result = new MemoryReturnType();
boolean sorted = false;
while (!sorted) {
sorted = true;
for (int i = 1; i < SIZE; i++) {
if (values[i - 1] > values[i]) {
int tmp = values[i];
values[i] = values[i - 1];
values[i - 1] = tmp;
sorted = false;
}
}
}
result.setResult(MemoryMonitor.getInstance());
return result;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("Pre: ");
if (values == null) {
sb.append("Empty");
} else {
for (int i = 0; i < 10; i++) {
sb.append(values[i]).append(',');
}
}
return sb.toString();
}
private static void saveTest(String testName, Object[] test) {
File saveFile = null;
String tempDir = System.getProperty("java.io.tmpdir");
String fileSep = System.getProperty("file.separator");
String filename = String.format("%s%s%s.tmp", tempDir, fileSep,
testName);
saveFile = new File(filename);
ObjectOutputStream objOut = null;
try {
objOut = new ObjectOutputStream(new FileOutputStream(saveFile));
objOut.writeObject(test);
} catch (IOException ioEx) {
ioEx.printStackTrace();
} finally {
try {
objOut.close();
} catch (IOException ioEx) {
ioEx.printStackTrace();
} finally {
objOut = null;
}
}
}
private static Object[] loadTests(String testName) {
File testFile = null;
String tempDir = System.getProperty("java.io.tmpdir");
String fileSep = System.getProperty("file.separator");
String filename = String.format("%s%s%s.tmp", tempDir, fileSep,
testName);
testFile = new File(filename);
testFile.deleteOnExit();
ObjectInputStream objIn = null;
Object[] test = null;
try {
objIn = new ObjectInputStream(new FileInputStream(testFile));
test = (Object[]) objIn.readObject();
} catch (IOException ioEx) {
ioEx.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
objIn.close();
} catch (IOException ioEx) {
ioEx.printStackTrace();
} finally {
objIn = null;
}
}
return test;
}
public static class IntArrayReturnType implements AbstractReturnType<int[]> {
private static final long serialVersionUID = 3848424333243246817L;
private int[] val = null;
@Override
public void setResult(int[] result) {
val = result;
}
@Override
public int[] getResult() {
return val;
}
}
public static class MemoryReturnType implements
AbstractReturnType<MemoryMonitor> {
private static final long serialVersionUID = 3848524333243246817L;
private MemoryMonitor val = null;
@Override
public void setResult(MemoryMonitor result) {
val = result;
}
@Override
public MemoryMonitor getResult() {
return val;
}
@Override
public String toString() {
return val.toString();
}
}
}