package org.multiverse.stms.gamma.benchmarks;
import org.benchy.BenchyUtils;
import org.multiverse.TestThread;
import org.multiverse.api.LockMode;
import org.multiverse.stms.gamma.GammaConstants;
import org.multiverse.stms.gamma.GammaStm;
import org.multiverse.stms.gamma.transactionalobjects.GammaTxnLong;
import org.multiverse.stms.gamma.transactions.GammaTxnConfig;
import org.multiverse.stms.gamma.transactions.fat.FatMonoGammaTxn;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.assertEquals;
import static org.multiverse.TestUtils.joinAll;
import static org.multiverse.TestUtils.startAll;
import static org.multiverse.stms.gamma.benchmarks.BenchmarkUtils.*;
public class UncontendedLeanUpdateBenchmark implements GammaConstants {
private GammaStm stm;
public static void main(String[] args) {
UncontendedLeanUpdateBenchmark test = new UncontendedLeanUpdateBenchmark();
test.start(Long.parseLong(args[0]));
}
public void start(long transactionCount) {
int[] processors = generateProcessorRange();
System.out.printf("Multiverse> Uncontended update lean-transaction benchmark\n");
System.out.printf("Multiverse> 1 GammaTxnRef per transaction\n");
System.out.printf("Multiverse> %s Transactions per thread\n", format(transactionCount));
System.out.printf("Multiverse> Running with the following processor range %s\n", Arrays.toString(processors));
Result[] result = new Result[processors.length];
System.out.println("Multiverse> Starting warmup run");
test(1, transactionCount);
System.out.println("Multiverse> Finished warmup run");
long startNs = System.nanoTime();
for (int k = 0; k < processors.length; k++) {
int processorCount = processors[k];
double performance = test(processorCount, transactionCount);
result[k] = new Result(processorCount, performance);
}
long durationNs = System.nanoTime() - startNs;
System.out.printf("Multiverse> Benchmark took %s seconds\n", TimeUnit.NANOSECONDS.toSeconds(durationNs));
toGnuplot(result);
}
private double test(int threadCount, long transactionsPerThread) {
System.out.printf("Multiverse> ----------------------------------------------\n");
System.out.printf("Multiverse> Running with %s thread(s)\n", threadCount);
stm = new GammaStm();
UpdateThread[] threads = new UpdateThread[threadCount];
for (int k = 0; k < threads.length; k++) {
threads[k] = new UpdateThread(k, transactionsPerThread);
}
startAll(threads);
joinAll(threads);
long totalDurationMs = 0;
for (UpdateThread t : threads) {
totalDurationMs += t.durationMs;
}
double transactionsPerSecond = transactionsPerSecondPerThread(
transactionsPerThread, totalDurationMs, threadCount);
System.out.printf("Multiverse> Threadcount %s\n", threadCount);
System.out.printf("Multiverse> Performance %s transactions/second/thread\n",
BenchyUtils.format(transactionsPerSecond));
System.out.printf("Multiverse> Performance %s transactions/second\n",
transactionsPerSecondAsString(transactionsPerThread, totalDurationMs, threadCount));
return transactionsPerSecond;
}
class UpdateThread extends TestThread {
private final long transactionCount;
private long durationMs;
public UpdateThread(int id, long transactionCount) {
super("UpdateThread-" + id);
setPriority(Thread.MAX_PRIORITY);
this.transactionCount = transactionCount;
}
public void doRun() {
GammaTxnLong ref = new GammaTxnLong(stm);
//FatArrayTreeGammaTxn tx = new FatArrayTreeGammaTxn(stm);
//FatArrayGammaTxn tx = new FatArrayGammaTxn(stm,1);
FatMonoGammaTxn tx = new FatMonoGammaTxn(
new GammaTxnConfig(stm)
.setReadLockMode(LockMode.Exclusive)
.setDirtyCheckEnabled(false));
long startMs = System.currentTimeMillis();
for (long k = 0; k < transactionCount; k++) {
ref.openForWrite(tx, LOCKMODE_EXCLUSIVE).long_value++;
tx.commit();
tx.hardReset();
//if (k % 100000000 == 0 && k > 0) {
// System.out.printf("%s is at %s\n", getName(), k);
//}
}
assertEquals(transactionCount, ref.atomicGet());
durationMs = System.currentTimeMillis() - startMs;
System.out.printf("Multiverse> %s is finished in %s ms\n", getName(), durationMs);
}
}
}