package contention.benchmark;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Formatter;
import java.util.Locale;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import contention.abstractions.CompositionalIntSet;
import contention.abstractions.CompositionalMap;
import contention.abstractions.CompositionalSortedSet;
import contention.abstractions.MaintenanceAlg;
/**
* Synchrobench-java, a benchmark to evaluate the implementations of
* high level abstractions including Map and Set.
*
* @author Vincent Gramoli
*
*/
public class Test {
public static final String VERSION = "11-17-2014";
public enum Type {
INTSET, MAP, SORTEDSET
}
/** The array of threads executing the benchmark */
private Thread[] threads;
/** The array of runnable thread codes */
private ThreadLoop[] threadLoops;
private ThreadSetLoop[] threadLoopsSet;
private ThreadSortedSetLoop[] threadLoopsSSet;
/** The observed duration of the benchmark */
private double elapsedTime;
/** The throughput */
private double[] throughput = null;
/** The iteration */
private int currentIteration = 0;
/** The total number of operations for all threads */
private long total = 0;
/** The total number of successful operations for all threads */
private long numAdd = 0;
private long numRemove = 0;
private long numAddAll = 0;
private long numRemoveAll = 0;
private long numSize = 0;
private long numContains = 0;
/** The total number of failed operations for all threads */
private long failures = 0;
/** The total number of aborts */
private long aborts = 0;
/** The instance of the benchmark */
private Type benchType = null;
private CompositionalIntSet setBench = null;
private CompositionalSortedSet<Integer> sortedBench = null;
private CompositionalMap<Integer, Integer> mapBench = null;
ConcurrentHashMap<Integer, Integer> map = null;
/** The instance of the benchmark */
/** The benchmark methods */
private Method[] methods;
private long nodesTraversed;
public long structMods;
private long getCount;
/** The thread-private PRNG */
final private static ThreadLocal<Random> s_random = new ThreadLocal<Random>() {
@Override
protected synchronized Random initialValue() {
return new Random();
}
};
public void fill(final int range, final long size) {
for (long i = size; i > 0;) {
Integer v = s_random.get().nextInt(range);
switch(benchType) {
case INTSET:
if (setBench.addInt(v)) {
i--;
}
break;
case MAP:
if (mapBench.putIfAbsent((Integer) v, (Integer) v) == null) {
i--;
}
break;
case SORTEDSET:
if (sortedBench.add((Integer) v)) {
i--;
}
break;
default:
System.err.println("Wrong benchmark type");
System.exit(0);
}
}
}
/**
* Initialize the benchmark
*
* @param benchName
* the class name of the benchmark
* @return the instance of the initialized corresponding benchmark
*/
@SuppressWarnings("unchecked")
public void instanciateAbstraction(
String benchName) {
try {
Class<CompositionalMap<Integer, Integer>> benchClass = (Class<CompositionalMap<Integer, Integer>>) Class
.forName(benchName);
Constructor<CompositionalMap<Integer, Integer>> c = benchClass
.getConstructor();
methods = benchClass.getDeclaredMethods();
if (CompositionalIntSet.class.isAssignableFrom((Class<?>) benchClass)) {
setBench = (CompositionalIntSet)c.newInstance();
benchType = Type.INTSET;
} else if (CompositionalMap.class.isAssignableFrom((Class<?>) benchClass)) {
mapBench = (CompositionalMap<Integer, Integer>) c.newInstance();
benchType = Type.MAP;
} else if (CompositionalSortedSet.class.isAssignableFrom((Class<?>) benchClass)) {
sortedBench = (CompositionalSortedSet<Integer>) c.newInstance();
benchType = Type.SORTEDSET;
}
} catch (Exception e) {
System.err.println("Cannot find benchmark class: " + benchName);
System.exit(-1);
}
}
/**
* Creates as many threads as requested
*
* @throws InterruptedException
* if unable to launch them
*/
private void initThreads() throws InterruptedException {
switch(benchType) {
case INTSET:
threadLoopsSet = new ThreadSetLoop[Parameters.numThreads];
threads = new Thread[Parameters.numThreads];
for (short threadNum = 0; threadNum < Parameters.numThreads; threadNum++) {
threadLoopsSet[threadNum] = new ThreadSetLoop(threadNum, setBench, methods);
threads[threadNum] = new Thread(threadLoopsSet[threadNum]);
}
break;
case MAP:
threadLoops = new ThreadLoop[Parameters.numThreads];
threads = new Thread[Parameters.numThreads];
for (short threadNum = 0; threadNum < Parameters.numThreads; threadNum++) {
threadLoops[threadNum] = new ThreadLoop(threadNum, mapBench, methods);
threads[threadNum] = new Thread(threadLoops[threadNum]);
}
break;
case SORTEDSET:
threadLoopsSSet = new ThreadSortedSetLoop[Parameters.numThreads];
threads = new Thread[Parameters.numThreads];
for (short threadNum = 0; threadNum < Parameters.numThreads; threadNum++) {
threadLoopsSSet[threadNum] = new ThreadSortedSetLoop(threadNum, sortedBench, methods);
threads[threadNum] = new Thread(threadLoopsSSet[threadNum]);
}
break;
}
}
/**
* Constructor sets up the benchmark by reading parameters and creating
* threads
*
* @param args
* the arguments of the command-line
*/
public Test(String[] args) throws InterruptedException {
printHeader();
try {
parseCommandLineParameters(args);
} catch (Exception e) {
System.err.println("Cannot parse parameters.");
e.printStackTrace();
}
instanciateAbstraction(Parameters.benchClassName);
this.throughput = new double[Parameters.iterations];
}
/**
* Execute the main thread that starts and terminates the benchmark threads
*
* @throws InterruptedException
*/
private void execute(int milliseconds, boolean maint)
throws InterruptedException {
long startTime;
fill(Parameters.range, Parameters.size);
Thread.sleep(5000);
startTime = System.currentTimeMillis();
for (Thread thread : threads)
thread.start();
try {
Thread.sleep(milliseconds);
} finally {
switch(benchType) {
case INTSET:
for (ThreadSetLoop threadLoop : threadLoopsSet)
threadLoop.stopThread();
break;
case MAP:
for (ThreadLoop threadLoop : threadLoops)
threadLoop.stopThread();
break;
case SORTEDSET:
for (ThreadSortedSetLoop threadLoop : threadLoopsSSet)
threadLoop.stopThread();
break;
}
}
for (Thread thread : threads)
thread.join();
long endTime = System.currentTimeMillis();
elapsedTime = ((double) (endTime - startTime)) / 1000.0;
}
public void clear() {
switch(benchType) {
case INTSET:
setBench.clear();
break;
case MAP:
mapBench.clear();
break;
case SORTEDSET:
sortedBench.clear();
break;
}
}
public static void main(String[] args) throws InterruptedException {
boolean firstIteration = true;
Test test = new Test(args);
test.printParams();
// warming up the JVM
if (Parameters.warmUp != 0) {
try {
test.initThreads();
} catch (Exception e) {
System.err.println("Cannot launch operations.");
e.printStackTrace();
}
test.execute(Parameters.warmUp * 1000, true);
// give time to the JIT
Thread.sleep(1000);
if (Parameters.detailedStats)
test.recordPreliminaryStats();
test.clear();
test.resetStats();
}
// running the bench
for (int i = 0; i < Parameters.iterations; i++) {
if (!firstIteration) {
// give time to the JIT
Thread.sleep(1000);
test.resetStats();
test.clear();
org.deuce.transaction.estmstats.Context.threadIdCounter.set(0);
}
try {
test.initThreads();
} catch (Exception e) {
System.err.println("Cannot launch operations.");
e.printStackTrace();
}
test.execute(Parameters.numMilliseconds, false);
if (test.setBench instanceof MaintenanceAlg) {
((MaintenanceAlg) test.setBench).stopMaintenance();
test.structMods += ((MaintenanceAlg) test.setBench)
.getStructMods();
}
if (test.mapBench instanceof MaintenanceAlg) {
((MaintenanceAlg) test.mapBench).stopMaintenance();
test.structMods += ((MaintenanceAlg) test.mapBench)
.getStructMods();
}
if (test.sortedBench instanceof MaintenanceAlg) {
((MaintenanceAlg) test.sortedBench).stopMaintenance();
test.structMods += ((MaintenanceAlg) test.sortedBench)
.getStructMods();
}
test.printBasicStats();
if (Parameters.detailedStats)
test.printDetailedStats();
firstIteration = false;
test.currentIteration++;
}
if (Parameters.iterations > 1) {
test.printIterationStats();
}
}
/* ---------------- Input/Output -------------- */
/**
* Parse the parameters on the command line
*/
private void parseCommandLineParameters(String[] args) throws Exception {
int argNumber = 0;
while (argNumber < args.length) {
String currentArg = args[argNumber++];
try {
if (currentArg.equals("--help") || currentArg.equals("-h")) {
printUsage();
System.exit(0);
} else if (currentArg.equals("--verbose")
|| currentArg.equals("-v")) {
Parameters.detailedStats = true;
} else {
String optionValue = args[argNumber++];
if (currentArg.equals("--thread-nums")
|| currentArg.equals("-t"))
Parameters.numThreads = Integer.parseInt(optionValue);
else if (currentArg.equals("--duration")
|| currentArg.equals("-d"))
Parameters.numMilliseconds = Integer
.parseInt(optionValue);
else if (currentArg.equals("--updates")
|| currentArg.equals("-u"))
Parameters.numWrites = Integer.parseInt(optionValue);
else if (currentArg.equals("--writeAll")
|| currentArg.equals("-a"))
Parameters.numWriteAlls = Integer.parseInt(optionValue);
else if (currentArg.equals("--snapshots")
|| currentArg.equals("-s"))
Parameters.numSnapshots = Integer.parseInt(optionValue);
else if (currentArg.equals("--size")
|| currentArg.equals("-i"))
Parameters.size = Integer.parseInt(optionValue);
else if (currentArg.equals("--range")
|| currentArg.equals("-r"))
Parameters.range = Integer.parseInt(optionValue);
else if (currentArg.equals("--Warmup")
|| currentArg.equals("-W"))
Parameters.warmUp = Integer.parseInt(optionValue);
else if (currentArg.equals("--benchmark")
|| currentArg.equals("-b"))
Parameters.benchClassName = optionValue;
else if (currentArg.equals("--iterations")
|| currentArg.equals("-n"))
Parameters.iterations = Integer.parseInt(optionValue);
}
} catch (IndexOutOfBoundsException e) {
System.err.println("Missing value after option: " + currentArg
+ ". Ignoring...");
} catch (NumberFormatException e) {
System.err.println("Number expected after option: "
+ currentArg + ". Ignoring...");
}
}
assert (Parameters.range >= Parameters.size);
if (Parameters.range != 2 * Parameters.size)
System.err
.println("Note that the value range is not twice "
+ "the initial size, thus the size expectation varies at runtime.");
}
/**
* Print a 80 character line filled with the same marker character
*
* @param ch
* the marker character
*/
private void printLine(char ch) {
StringBuffer line = new StringBuffer(79);
for (int i = 0; i < 79; i++)
line.append(ch);
System.out.println(line);
}
/**
* Print the header message on the standard output
*/
private void printHeader() {
String header = "Synchrobench-java\n"
+ "A benchmark-suite to evaluate synchronization techniques";
printLine('-');
System.out.println(header);
printLine('-');
System.out.println();
}
/**
* Print the benchmark usage on the standard output
*/
private void printUsage() {
String syntax = "Usage:\n"
+ "java synchrobench.benchmark.Test [options] [-- stm-specific options]\n\n"
+ "Options:\n"
+ "\t-v -- print detailed statistics (default: "
+ Parameters.detailedStats
+ ")\n"
+ "\t-t thread-num -- set the number of threads (default: "
+ Parameters.numThreads
+ ")\n"
+ "\t-d duration -- set the length of the benchmark, in milliseconds (default: "
+ Parameters.numMilliseconds
+ ")\n"
+ "\t-u updates -- set the number of threads (default: "
+ Parameters.numWrites
+ ")\n"
+ "\t-a writeAll -- set the percentage of composite updates (default: "
+ Parameters.numWriteAlls
+ ")\n"
+ "\t-s snapshot -- set the percentage of composite read-only operations (default: "
+ Parameters.numSnapshots
+ ")\n"
+ "\t-r range -- set the element range (default: "
+ Parameters.range
+ ")\n"
+ "\t-b benchmark -- set the benchmark (default: "
+ Parameters.benchClassName
+ ")\n"
+ "\t-i size -- set the datastructure initial size (default: "
+ Parameters.size
+ ")\n"
+ "\t-n iterations -- set the bench iterations in the same JVM (default: "
+ Parameters.iterations
+ ")\n"
+ "\t-W warmup -- set the JVM warmup length, in seconds (default: "
+ Parameters.warmUp + ").";
System.err.println(syntax);
}
/**
* Print the parameters that have been given as an input to the benchmark
*/
private void printParams() {
String params = "Benchmark parameters" + "\n" + "--------------------"
+ "\n" + " Detailed stats: \t"
+ (Parameters.detailedStats ? "enabled" : "disabled")
+ "\n"
+ " Number of threads: \t"
+ Parameters.numThreads
+ "\n"
+ " Length: \t"
+ Parameters.numMilliseconds
+ " ms\n"
+ " Write ratio: \t"
+ Parameters.numWrites
+ " %\n"
+ " WriteAll ratio: \t"
+ Parameters.numWriteAlls
+ " %\n"
+ " Snapshot ratio: \t"
+ Parameters.numSnapshots
+ " %\n"
+ " Size: \t"
+ Parameters.size
+ " elts\n"
+ " Range: \t"
+ Parameters.range
+ " elts\n"
+ " WarmUp: \t"
+ Parameters.warmUp
+ " s\n"
+ " Iterations: \t"
+ Parameters.iterations
+ "\n"
+ " Benchmark: \t"
+ Parameters.benchClassName;
System.out.println(params);
}
/**
* Print the statistics on the standard output
*/
private void printBasicStats() {
for (short threadNum = 0; threadNum < Parameters.numThreads; threadNum++) {
switch(benchType) {
case INTSET:
numAdd += threadLoopsSet[threadNum].numAdd;
numRemove += threadLoopsSet[threadNum].numRemove;
numAddAll += threadLoopsSet[threadNum].numAddAll;
numRemoveAll += threadLoopsSet[threadNum].numRemoveAll;
numSize += threadLoopsSet[threadNum].numSize;
numContains += threadLoopsSet[threadNum].numContains;
failures += threadLoopsSet[threadNum].failures;
total += threadLoopsSet[threadNum].total;
aborts += threadLoopsSet[threadNum].aborts;
getCount += threadLoopsSet[threadNum].getCount;
nodesTraversed += threadLoopsSet[threadNum].nodesTraversed;
structMods += threadLoopsSet[threadNum].structMods;
break;
case MAP:
numAdd += threadLoops[threadNum].numAdd;
numRemove += threadLoops[threadNum].numRemove;
numAddAll += threadLoops[threadNum].numAddAll;
numRemoveAll += threadLoops[threadNum].numRemoveAll;
numSize += threadLoops[threadNum].numSize;
numContains += threadLoops[threadNum].numContains;
failures += threadLoops[threadNum].failures;
total += threadLoops[threadNum].total;
aborts += threadLoops[threadNum].aborts;
getCount += threadLoops[threadNum].getCount;
nodesTraversed += threadLoops[threadNum].nodesTraversed;
structMods += threadLoops[threadNum].structMods;
break;
case SORTEDSET:
numAdd += threadLoopsSSet[threadNum].numAdd;
numRemove += threadLoopsSSet[threadNum].numRemove;
numAddAll += threadLoopsSSet[threadNum].numAddAll;
numRemoveAll += threadLoopsSSet[threadNum].numRemoveAll;
numSize += threadLoopsSSet[threadNum].numSize;
numContains += threadLoopsSSet[threadNum].numContains;
failures += threadLoopsSSet[threadNum].failures;
total += threadLoopsSSet[threadNum].total;
aborts += threadLoopsSSet[threadNum].aborts;
getCount += threadLoopsSSet[threadNum].getCount;
nodesTraversed += threadLoopsSSet[threadNum].nodesTraversed;
structMods += threadLoopsSSet[threadNum].structMods;
break;
}
}
throughput[currentIteration] = ((double) total / elapsedTime);
printLine('-');
System.out.println("Benchmark statistics");
printLine('-');
System.out.println(" Average traversal length: \t"
+ (double) nodesTraversed / (double) getCount);
System.out.println(" Struct Modifications: \t" + structMods);
System.out.println(" Throughput (ops/s): \t" + throughput[currentIteration]);
System.out.println(" Elapsed time (s): \t" + elapsedTime);
System.out.println(" Operations: \t" + total
+ "\t( 100 %)");
System.out
.println(" effective updates: \t"
+ (numAdd + numRemove + numAddAll + numRemoveAll)
+ "\t( "
+ formatDouble(((double) (numAdd + numRemove
+ numAddAll + numRemoveAll) * 100)
/ (double) total) + " %)");
System.out.println(" |--add successful: \t" + numAdd + "\t( "
+ formatDouble(((double) numAdd / (double) total) * 100)
+ " %)");
System.out.println(" |--remove succ.: \t" + numRemove + "\t( "
+ formatDouble(((double) numRemove / (double) total) * 100)
+ " %)");
System.out.println(" |--addAll succ.: \t" + numAddAll + "\t( "
+ formatDouble(((double) numAddAll / (double) total) * 100)
+ " %)");
System.out.println(" |--removeAll succ.: \t" + numRemoveAll
+ "\t( "
+ formatDouble(((double) numRemoveAll / (double) total) * 100)
+ " %)");
System.out.println(" size successful: \t" + numSize + "\t( "
+ formatDouble(((double) numSize / (double) total) * 100)
+ " %)");
System.out.println(" contains succ.: \t" + numContains
+ "\t( "
+ formatDouble(((double) numContains / (double) total) * 100)
+ " %)");
System.out.println(" unsuccessful ops: \t" + failures + "\t( "
+ formatDouble(((double) failures / (double) total) * 100)
+ " %)");
switch(benchType) {
case INTSET:
System.out.println(" Final size: \t" + setBench.size());
if (Parameters.numWriteAlls == 0) System.out.println(" Expected size: \t" + (Parameters.size+numAdd-numRemove));
break;
case MAP:
System.out.println(" Final size: \t" + mapBench.size());
if (Parameters.numWriteAlls == 0) System.out.println(" Expected size: \t" + (Parameters.size+numAdd-numRemove));
break;
case SORTEDSET:
System.out.println(" Final size: \t" + sortedBench.size());
if (Parameters.numWriteAlls == 0) System.out.println(" Expected size: \t" + (Parameters.size+numAdd-numRemove));
break;
}
//System.out.println(" Other size: \t" + map.size());
// TODO what should print special for maint data structures
// if (bench instanceof CASSpecFriendlyTreeLockFree) {
// System.out.println(" Balance: \t"
// + ((CASSpecFriendlyTreeLockFree) bench).getBalance());
// }
// if (bench instanceof SpecFriendlyTreeLockFree) {
// System.out.println(" Balance: \t"
// + ((SpecFriendlyTreeLockFree) bench).getBalance());
// }
// if (bench instanceof TransFriendlyMap) {
// System.out.println(" Balance: \t"
// + ((TransFriendlyMap) bench).getBalance());
// }
// if (bench instanceof UpdatedTransFriendlySkipList) {
// System.out.println(" Bottom changes: \t"
// + ((UpdatedTransFriendlySkipList) bench)
// .getBottomLevelRaiseCount());
// }
switch(benchType) {
case INTSET:
if (setBench instanceof MaintenanceAlg) {
System.out.println(" #nodes (inc. deleted): \t"
+ ((MaintenanceAlg) setBench).numNodes());
}
break;
case MAP:
if (mapBench instanceof MaintenanceAlg) {
System.out.println(" #nodes (inc. deleted): \t"
+ ((MaintenanceAlg) mapBench).numNodes());
}
break;
case SORTEDSET:
if (mapBench instanceof MaintenanceAlg) {
System.out.println(" #nodes (inc. deleted): \t"
+ ((MaintenanceAlg) sortedBench).numNodes());
}
break;
}
}
/**
* Detailed Warmup TM Statistics
*/
private int numCommits = 0;
private int numStarts = 0;
private int numAborts = 0;
private int numCommitsReadOnly = 0;
private int numCommitsElastic = 0;
private int numCommitsUpdate = 0;
private int numAbortsBetweenSuccessiveReads = 0;
private int numAbortsBetweenReadAndWrite = 0;
private int numAbortsExtendOnRead = 0;
private int numAbortsWriteAfterRead = 0;
private int numAbortsLockedOnWrite = 0;
private int numAbortsLockedBeforeRead = 0;
private int numAbortsLockedBeforeElasticRead = 0;
private int numAbortsLockedOnRead = 0;
private int numAbortsInvalidCommit = 0;
private int numAbortsInvalidSnapshot = 0;
private double readSetSizeSum = 0.0;
private double writeSetSizeSum = 0.0;
private int statSize = 0;
private int txDurationSum = 0;
private int elasticReads = 0;
private int readsInROPrefix = 0;
/**
* This method is called between two runs of the benchmark within the same
* JVM to enable its warmup
*/
public void resetStats() {
for (short threadNum = 0; threadNum < Parameters.numThreads; threadNum++) {
switch (benchType) {
case INTSET:
threadLoopsSet[threadNum].numAdd = 0;
threadLoopsSet[threadNum].numRemove = 0;
threadLoopsSet[threadNum].numAddAll = 0;
threadLoopsSet[threadNum].numRemoveAll = 0;
threadLoopsSet[threadNum].numSize = 0;
threadLoopsSet[threadNum].numContains = 0;
threadLoopsSet[threadNum].failures = 0;
threadLoopsSet[threadNum].total = 0;
threadLoopsSet[threadNum].aborts = 0;
threadLoopsSet[threadNum].nodesTraversed = 0;
threadLoopsSet[threadNum].getCount = 0;
threadLoopsSet[threadNum].structMods = 0;
break;
case MAP:
threadLoops[threadNum].numAdd = 0;
threadLoops[threadNum].numRemove = 0;
threadLoops[threadNum].numAddAll = 0;
threadLoops[threadNum].numRemoveAll = 0;
threadLoops[threadNum].numSize = 0;
threadLoops[threadNum].numContains = 0;
threadLoops[threadNum].failures = 0;
threadLoops[threadNum].total = 0;
threadLoops[threadNum].aborts = 0;
threadLoops[threadNum].nodesTraversed = 0;
threadLoops[threadNum].getCount = 0;
threadLoops[threadNum].structMods = 0;
break;
case SORTEDSET:
threadLoopsSSet[threadNum].numAdd = 0;
threadLoopsSSet[threadNum].numRemove = 0;
threadLoopsSSet[threadNum].numAddAll = 0;
threadLoopsSSet[threadNum].numRemoveAll = 0;
threadLoopsSSet[threadNum].numSize = 0;
threadLoopsSSet[threadNum].numContains = 0;
threadLoopsSSet[threadNum].failures = 0;
threadLoopsSSet[threadNum].total = 0;
threadLoopsSSet[threadNum].aborts = 0;
threadLoopsSSet[threadNum].nodesTraversed = 0;
threadLoopsSSet[threadNum].getCount = 0;
threadLoopsSSet[threadNum].structMods = 0;
break;
}
}
numAdd = 0;
numRemove = 0;
numAddAll = 0;
numRemoveAll = 0;
numSize = 0;
numContains = 0;
failures = 0;
total = 0;
aborts = 0;
nodesTraversed = 0;
getCount = 0;
structMods = 0;
numCommits = 0;
numStarts = 0;
numAborts = 0;
numCommitsReadOnly = 0;
numCommitsElastic = 0;
numCommitsUpdate = 0;
numAbortsBetweenSuccessiveReads = 0;
numAbortsBetweenReadAndWrite = 0;
numAbortsExtendOnRead = 0;
numAbortsWriteAfterRead = 0;
numAbortsLockedOnWrite = 0;
numAbortsLockedBeforeRead = 0;
numAbortsLockedBeforeElasticRead = 0;
numAbortsLockedOnRead = 0;
numAbortsInvalidCommit = 0;
numAbortsInvalidSnapshot = 0;
readSetSizeSum = 0.0;
writeSetSizeSum = 0.0;
statSize = 0;
txDurationSum = 0;
elasticReads = 0;
readsInROPrefix = 0;
}
public void recordPreliminaryStats() {
numAborts = Statistics.getTotalAborts();
numCommits = Statistics.getTotalCommits();
numCommitsReadOnly = Statistics.getNumCommitsReadOnly();
numCommitsElastic = Statistics.getNumCommitsElastic();
numCommitsUpdate = Statistics.getNumCommitsUpdate();
numStarts = Statistics.getTotalStarts();
numAbortsBetweenSuccessiveReads = Statistics
.getNumAbortsBetweenSuccessiveReads();
numAbortsBetweenReadAndWrite = Statistics
.getNumAbortsBetweenReadAndWrite();
numAbortsExtendOnRead = Statistics.getNumAbortsExtendOnRead();
numAbortsWriteAfterRead = Statistics.getNumAbortsWriteAfterRead();
numAbortsLockedOnWrite = Statistics.getNumAbortsLockedOnWrite();
numAbortsLockedBeforeRead = Statistics.getNumAbortsLockedBeforeRead();
numAbortsLockedBeforeElasticRead = Statistics
.getNumAbortsLockedBeforeElasticRead();
numAbortsLockedOnRead = Statistics.getNumAbortsLockedOnRead();
numAbortsInvalidCommit = Statistics.getNumAbortsInvalidCommit();
numAbortsInvalidSnapshot = Statistics.getNumAbortsInvalidSnapshot();
readSetSizeSum = Statistics.getSumReadSetSize();
writeSetSizeSum = Statistics.getSumWriteSetSize();
;
statSize = Statistics.getStatSize();
txDurationSum = Statistics.getSumCommitingTxTime();
elasticReads = Statistics.getTotalElasticReads();
readsInROPrefix = Statistics.getTotalReadsInROPrefix();
}
/**
* Print the detailed statistics on the standard output
*/
private void printDetailedStats() {
numCommits = Statistics.getTotalCommits() - numCommits;
numStarts = Statistics.getTotalStarts() - numStarts;
numAborts = Statistics.getTotalAborts() - numAborts;
numCommitsReadOnly = Statistics.getNumCommitsReadOnly()
- numCommitsReadOnly;
numCommitsElastic = Statistics.getNumCommitsElastic()
- numCommitsElastic;
numCommitsUpdate = Statistics.getNumCommitsUpdate() - numCommitsUpdate;
numAbortsBetweenSuccessiveReads = Statistics
.getNumAbortsBetweenSuccessiveReads()
- numAbortsBetweenSuccessiveReads;
numAbortsBetweenReadAndWrite = Statistics
.getNumAbortsBetweenReadAndWrite()
- numAbortsBetweenReadAndWrite;
numAbortsExtendOnRead = Statistics.getNumAbortsExtendOnRead()
- numAbortsExtendOnRead;
numAbortsWriteAfterRead = Statistics.getNumAbortsWriteAfterRead()
- numAbortsWriteAfterRead;
numAbortsLockedOnWrite = Statistics.getNumAbortsLockedOnWrite()
- numAbortsLockedOnWrite;
numAbortsLockedBeforeRead = Statistics.getNumAbortsLockedBeforeRead()
- numAbortsLockedBeforeRead;
numAbortsLockedBeforeElasticRead = Statistics
.getNumAbortsLockedBeforeElasticRead()
- numAbortsLockedBeforeElasticRead;
numAbortsLockedOnRead = Statistics.getNumAbortsLockedOnRead()
- numAbortsLockedOnRead;
numAbortsInvalidCommit = Statistics.getNumAbortsInvalidCommit()
- numAbortsInvalidCommit;
numAbortsInvalidSnapshot = Statistics.getNumAbortsInvalidSnapshot()
- numAbortsInvalidSnapshot;
assert (numAborts == (numAbortsBetweenSuccessiveReads
+ numAbortsBetweenReadAndWrite + numAbortsExtendOnRead
+ numAbortsWriteAfterRead + numAbortsLockedOnWrite
+ numAbortsLockedBeforeRead + numAbortsLockedBeforeElasticRead
+ numAbortsLockedOnRead + numAbortsInvalidCommit + numAbortsInvalidSnapshot));
assert (numStarts - numAborts) == numCommits;
readSetSizeSum = Statistics.getSumReadSetSize() - readSetSizeSum;
writeSetSizeSum = Statistics.getSumWriteSetSize() - writeSetSizeSum;
statSize = Statistics.getStatSize() - statSize;
txDurationSum = Statistics.getSumCommitingTxTime() - txDurationSum;
printLine('-');
System.out.println("TM statistics");
printLine('-');
System.out.println(" Commits: \t" + numCommits);
System.out
.println(" |--regular read only (%) \t"
+ numCommitsReadOnly
+ "\t( "
+ formatDouble(((double) numCommitsReadOnly / (double) numCommits) * 100)
+ " %)");
System.out
.println(" |--elastic (%) \t"
+ numCommitsElastic
+ "\t( "
+ formatDouble(((double) numCommitsElastic / (double) numCommits) * 100)
+ " %)");
System.out
.println(" |--regular update (%) \t"
+ numCommitsUpdate
+ "\t( "
+ formatDouble(((double) numCommitsUpdate / (double) numCommits) * 100)
+ " %)");
System.out.println(" Starts: \t" + numStarts);
System.out.println(" Aborts: \t" + numAborts
+ "\t( 100 %)");
System.out
.println(" |--between succ. reads: \t"
+ (numAbortsBetweenSuccessiveReads)
+ "\t( "
+ formatDouble(((double) (numAbortsBetweenSuccessiveReads) * 100)
/ (double) numAborts) + " %)");
System.out
.println(" |--between read & write: \t"
+ numAbortsBetweenReadAndWrite
+ "\t( "
+ formatDouble(((double) numAbortsBetweenReadAndWrite / (double) numAborts) * 100)
+ " %)");
System.out
.println(" |--extend upon read: \t"
+ numAbortsExtendOnRead
+ "\t( "
+ formatDouble(((double) numAbortsExtendOnRead / (double) numAborts) * 100)
+ " %)");
System.out
.println(" |--write after read: \t"
+ numAbortsWriteAfterRead
+ "\t( "
+ formatDouble(((double) numAbortsWriteAfterRead / (double) numAborts) * 100)
+ " %)");
System.out
.println(" |--locked on write: \t"
+ numAbortsLockedOnWrite
+ "\t( "
+ formatDouble(((double) numAbortsLockedOnWrite / (double) numAborts) * 100)
+ " %)");
System.out
.println(" |--locked before read: \t"
+ numAbortsLockedBeforeRead
+ "\t( "
+ formatDouble(((double) numAbortsLockedBeforeRead / (double) numAborts) * 100)
+ " %)");
System.out
.println(" |--locked before eread: \t"
+ numAbortsLockedBeforeElasticRead
+ "\t( "
+ formatDouble(((double) numAbortsLockedBeforeElasticRead / (double) numAborts) * 100)
+ " %)");
System.out
.println(" |--locked on read: \t"
+ numAbortsLockedOnRead
+ "\t( "
+ formatDouble(((double) numAbortsLockedOnRead / (double) numAborts) * 100)
+ " %)");
System.out
.println(" |--invalid commit: \t"
+ numAbortsInvalidCommit
+ "\t( "
+ formatDouble(((double) numAbortsInvalidCommit / (double) numAborts) * 100)
+ " %)");
System.out
.println(" |--invalid snapshot: \t"
+ numAbortsInvalidSnapshot
+ "\t( "
+ formatDouble(((double) numAbortsInvalidSnapshot / (double) numAborts) * 100)
+ " %)");
System.out.println(" Read set size on avg.: \t"
+ formatDouble(readSetSizeSum / statSize));
System.out.println(" Write set size on avg.: \t"
+ formatDouble(writeSetSizeSum / statSize));
System.out.println(" Tx time-to-commit on avg.:\t"
+ formatDouble((double) txDurationSum / numCommits)
+ " microsec");
System.out.println(" Number of elastic reads " + elasticReads);
System.out
.println(" Number of reads in RO prefix " + readsInROPrefix);
}
/**
* Print the iteration statistics on the standard output
*/
private void printIterationStats() {
printLine('-');
System.out.println("Iteration statistics");
printLine('-');
int n = Parameters.iterations;
System.out.println(" Iterations: \t" + n);
double sum = 0;
for (int i = 0; i < n; i++) {
sum += ((throughput[i]/1024)/1024);
}
System.out.println(" Total throughput (mebiops/s): " + sum);
double mean = sum / n;
System.out.println(" |--Mean: \t" + mean);
double temp = 0;
for (int i = 0; i < n; i++) {
double diff = ((throughput[i]/1024)/1024) - mean;
temp += diff * diff;
}
double var = temp / n;
System.out.println(" |--Variance: \t" + var);
double stdevp = java.lang.Math.sqrt(var);
System.out.println(" |--Standard deviation pop: \t" + stdevp);
double sterr = stdevp / java.lang.Math.sqrt(n);
System.out.println(" |--Standard error: \t" + sterr);
System.out.println(" |--Margin of error (95% CL):\t" + (sterr * 1.96));
}
private static String formatDouble(double result) {
Formatter formatter = new Formatter(Locale.US);
return formatter.format("%.2f", result).out().toString();
}
}