package org.multiverse.stms.gamma.benchmarks; import org.multiverse.TestThread; 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.FatFixedLengthGammaTxn; import java.util.Arrays; import java.util.concurrent.TimeUnit; import static org.benchy.BenchyUtils.format; import static org.multiverse.TestUtils.joinAll; import static org.multiverse.TestUtils.startAll; import static org.multiverse.stms.gamma.GammaTestUtils.makeReadBiased; /** * @author Peter Veentjer */ public class UncontendedMultipleReadBenchmark implements GammaConstants { private GammaStm stm; private final long transactionCount = 100 * 1000 * 1000; public static void main(String[] args) { //should be a power of two. int refCount = Integer.parseInt(args[0]); UncontendedMultipleReadBenchmark test = new UncontendedMultipleReadBenchmark(); test.start(refCount); } public void start(int refCount) { int[] processors = BenchmarkUtils.generateProcessorRange(); System.out.printf("Multiverse> Uncontended multiple read transaction benchmark\n"); System.out.printf("Multiverse> Running with the following processor range %s\n", Arrays.toString(processors)); System.out.printf("Multiverse> Running with %s transactionalobjects per transaction\n", refCount); System.out.printf("Multiverse> %s Transactions per thread\n", format(transactionCount)); Result[] result = new Result[processors.length]; System.out.printf("Multiverse> Starting warmup run\n"); test(1, 1); System.out.printf("Multiverse> Finished warmup run\n"); long startNs = System.nanoTime(); for (int k = 0; k < processors.length; k++) { int processorCount = processors[k]; double performance = test(processorCount, refCount); result[k] = new Result(processorCount, performance); } long durationNs = System.nanoTime() - startNs; System.out.printf("Benchmark took %s seconds\n", TimeUnit.NANOSECONDS.toSeconds(durationNs)); BenchmarkUtils.toGnuplot(result); } private double test(int threadCount, int refCount) { System.out.printf("Multiverse> Running with %s processors\n", threadCount); stm = new GammaStm(); ReadThread[] threads = new ReadThread[threadCount]; for (int k = 0; k < threads.length; k++) { threads[k] = new ReadThread(k, refCount); } startAll(threads); joinAll(threads); long totalDurationMs = 0; for (ReadThread t : threads) { totalDurationMs += t.durationMs; } double readsPerSecond = BenchmarkUtils.transactionsPerSecondPerThread( transactionCount * refCount, totalDurationMs, threadCount); System.out.printf("Multiverse> Performance %s reads/second with %s threads\n", format(readsPerSecond), threadCount); return readsPerSecond; } class ReadThread extends TestThread { private final int refCount; private long durationMs; public ReadThread(int id, int refCount) { super("ReadThread-" + id); setPriority(Thread.MAX_PRIORITY); this.refCount = refCount; } public void doRun() { switch (refCount) { case 1: run1(); break; case 2: run2(); break; case 4: run4(); break; case 8: run8(); break; case 16: run16(); break; case 32: run32(); break; default: throw new IllegalStateException(); } } public void run1() { GammaTxnLong ref1 = newReadBiasedLongRef(stm); GammaTxnConfig config = new GammaTxnConfig(stm, 1) .setReadonly(true); FatFixedLengthGammaTxn tx = new FatFixedLengthGammaTxn(config); long startMs = System.currentTimeMillis(); for (long iteration = 0; iteration < transactionCount; iteration++) { ref1.openForRead(tx, LOCKMODE_NONE); tx.commit(); tx.hardReset(); } durationMs = System.currentTimeMillis() - startMs; System.out.printf("Multiverse> %s is finished in %s ms\n", getName(), durationMs); } public void run2() { GammaTxnLong ref1 = newReadBiasedLongRef(stm); GammaTxnLong ref2 = newReadBiasedLongRef(stm); GammaTxnConfig config = new GammaTxnConfig(stm, 2) .setReadonly(true); FatFixedLengthGammaTxn tx = new FatFixedLengthGammaTxn(config); long startMs = System.currentTimeMillis(); for (long iteration = 0; iteration < transactionCount; iteration++) { ref1.openForRead(tx, LOCKMODE_NONE); ref2.openForRead(tx, LOCKMODE_NONE); tx.commit(); tx.hardReset(); } durationMs = System.currentTimeMillis() - startMs; System.out.printf("Multiverse> %s is finished in %s ms\n", getName(), durationMs); } public void run4() { GammaTxnLong ref1 = newReadBiasedLongRef(stm); GammaTxnLong ref2 = newReadBiasedLongRef(stm); GammaTxnLong ref3 = newReadBiasedLongRef(stm); GammaTxnLong ref4 = newReadBiasedLongRef(stm); GammaTxnConfig config = new GammaTxnConfig(stm, 4) .setReadonly(true); FatFixedLengthGammaTxn tx = new FatFixedLengthGammaTxn(config); long startMs = System.currentTimeMillis(); for (long iteration = 0; iteration < transactionCount; iteration++) { ref1.openForRead(tx, LOCKMODE_NONE); ref2.openForRead(tx, LOCKMODE_NONE); ref3.openForRead(tx, LOCKMODE_NONE); ref4.openForRead(tx, LOCKMODE_NONE); tx.commit(); tx.hardReset(); } durationMs = System.currentTimeMillis() - startMs; System.out.printf("Multiverse> %s is finished in %s ms\n", getName(), durationMs); } public void run8() { GammaTxnLong ref1 = newReadBiasedLongRef(stm); GammaTxnLong ref2 = newReadBiasedLongRef(stm); GammaTxnLong ref3 = newReadBiasedLongRef(stm); GammaTxnLong ref4 = newReadBiasedLongRef(stm); GammaTxnLong ref5 = newReadBiasedLongRef(stm); GammaTxnLong ref6 = newReadBiasedLongRef(stm); GammaTxnLong ref7 = newReadBiasedLongRef(stm); GammaTxnLong ref8 = newReadBiasedLongRef(stm); GammaTxnConfig config = new GammaTxnConfig(stm, 8) .setReadonly(true); FatFixedLengthGammaTxn tx = new FatFixedLengthGammaTxn(config); long startMs = System.currentTimeMillis(); for (long iteration = 0; iteration < transactionCount; iteration++) { ref1.openForRead(tx, LOCKMODE_NONE); ref2.openForRead(tx, LOCKMODE_NONE); ref3.openForRead(tx, LOCKMODE_NONE); ref4.openForRead(tx, LOCKMODE_NONE); ref5.openForRead(tx, LOCKMODE_NONE); ref6.openForRead(tx, LOCKMODE_NONE); ref7.openForRead(tx, LOCKMODE_NONE); ref8.openForRead(tx, LOCKMODE_NONE); tx.commit(); tx.hardReset(); } durationMs = System.currentTimeMillis() - startMs; System.out.printf("Multiverse> %s is finished in %s ms\n", getName(), durationMs); } public void run16() { GammaTxnLong ref1 = newReadBiasedLongRef(stm); GammaTxnLong ref2 = newReadBiasedLongRef(stm); GammaTxnLong ref3 = newReadBiasedLongRef(stm); GammaTxnLong ref4 = newReadBiasedLongRef(stm); GammaTxnLong ref5 = newReadBiasedLongRef(stm); GammaTxnLong ref6 = newReadBiasedLongRef(stm); GammaTxnLong ref7 = newReadBiasedLongRef(stm); GammaTxnLong ref8 = newReadBiasedLongRef(stm); GammaTxnLong ref9 = newReadBiasedLongRef(stm); GammaTxnLong ref10 = newReadBiasedLongRef(stm); GammaTxnLong ref11 = newReadBiasedLongRef(stm); GammaTxnLong ref12 = newReadBiasedLongRef(stm); GammaTxnLong ref13 = newReadBiasedLongRef(stm); GammaTxnLong ref14 = newReadBiasedLongRef(stm); GammaTxnLong ref15 = newReadBiasedLongRef(stm); GammaTxnLong ref16 = newReadBiasedLongRef(stm); GammaTxnConfig config = new GammaTxnConfig(stm, 16) .setReadonly(true); FatFixedLengthGammaTxn tx = new FatFixedLengthGammaTxn(config); long startMs = System.currentTimeMillis(); for (long iteration = 0; iteration < transactionCount; iteration++) { ref1.openForRead(tx, LOCKMODE_NONE); ref2.openForRead(tx, LOCKMODE_NONE); ref3.openForRead(tx, LOCKMODE_NONE); ref4.openForRead(tx, LOCKMODE_NONE); ref5.openForRead(tx, LOCKMODE_NONE); ref6.openForRead(tx, LOCKMODE_NONE); ref7.openForRead(tx, LOCKMODE_NONE); ref8.openForRead(tx, LOCKMODE_NONE); ref9.openForRead(tx, LOCKMODE_NONE); ref10.openForRead(tx, LOCKMODE_NONE); ref11.openForRead(tx, LOCKMODE_NONE); ref12.openForRead(tx, LOCKMODE_NONE); ref13.openForRead(tx, LOCKMODE_NONE); ref14.openForRead(tx, LOCKMODE_NONE); ref15.openForRead(tx, LOCKMODE_NONE); ref15.openForRead(tx, LOCKMODE_NONE); ref16.openForRead(tx, LOCKMODE_NONE); tx.commit(); tx.hardReset(); } durationMs = System.currentTimeMillis() - startMs; System.out.printf("Multiverse> %s is finished in %s ms\n", getName(), durationMs); } public void run32() { GammaTxnLong ref1 = newReadBiasedLongRef(stm); GammaTxnLong ref2 = newReadBiasedLongRef(stm); GammaTxnLong ref3 = newReadBiasedLongRef(stm); GammaTxnLong ref4 = newReadBiasedLongRef(stm); GammaTxnLong ref5 = newReadBiasedLongRef(stm); GammaTxnLong ref6 = newReadBiasedLongRef(stm); GammaTxnLong ref7 = newReadBiasedLongRef(stm); GammaTxnLong ref8 = newReadBiasedLongRef(stm); GammaTxnLong ref9 = newReadBiasedLongRef(stm); GammaTxnLong ref10 = newReadBiasedLongRef(stm); GammaTxnLong ref11 = newReadBiasedLongRef(stm); GammaTxnLong ref12 = newReadBiasedLongRef(stm); GammaTxnLong ref13 = newReadBiasedLongRef(stm); GammaTxnLong ref14 = newReadBiasedLongRef(stm); GammaTxnLong ref15 = newReadBiasedLongRef(stm); GammaTxnLong ref16 = newReadBiasedLongRef(stm); GammaTxnLong ref17 = newReadBiasedLongRef(stm); GammaTxnLong ref18 = newReadBiasedLongRef(stm); GammaTxnLong ref19 = newReadBiasedLongRef(stm); GammaTxnLong ref20 = newReadBiasedLongRef(stm); GammaTxnLong ref21 = newReadBiasedLongRef(stm); GammaTxnLong ref22 = newReadBiasedLongRef(stm); GammaTxnLong ref23 = newReadBiasedLongRef(stm); GammaTxnLong ref24 = newReadBiasedLongRef(stm); GammaTxnLong ref25 = newReadBiasedLongRef(stm); GammaTxnLong ref26 = newReadBiasedLongRef(stm); GammaTxnLong ref27 = newReadBiasedLongRef(stm); GammaTxnLong ref28 = newReadBiasedLongRef(stm); GammaTxnLong ref29 = newReadBiasedLongRef(stm); GammaTxnLong ref30 = newReadBiasedLongRef(stm); GammaTxnLong ref31 = newReadBiasedLongRef(stm); GammaTxnLong ref32 = newReadBiasedLongRef(stm); GammaTxnConfig config = new GammaTxnConfig(stm, 32) .setReadonly(true); FatFixedLengthGammaTxn tx = new FatFixedLengthGammaTxn(config); long startMs = System.currentTimeMillis(); for (long iteration = 0; iteration < transactionCount; iteration++) { ref1.openForRead(tx, LOCKMODE_NONE); ref2.openForRead(tx, LOCKMODE_NONE); ref3.openForRead(tx, LOCKMODE_NONE); ref4.openForRead(tx, LOCKMODE_NONE); ref5.openForRead(tx, LOCKMODE_NONE); ref6.openForRead(tx, LOCKMODE_NONE); ref7.openForRead(tx, LOCKMODE_NONE); ref8.openForRead(tx, LOCKMODE_NONE); ref9.openForRead(tx, LOCKMODE_NONE); ref10.openForRead(tx, LOCKMODE_NONE); ref11.openForRead(tx, LOCKMODE_NONE); ref12.openForRead(tx, LOCKMODE_NONE); ref13.openForRead(tx, LOCKMODE_NONE); ref14.openForRead(tx, LOCKMODE_NONE); ref15.openForRead(tx, LOCKMODE_NONE); ref15.openForRead(tx, LOCKMODE_NONE); ref16.openForRead(tx, LOCKMODE_NONE); ref17.openForRead(tx, LOCKMODE_NONE); ref18.openForRead(tx, LOCKMODE_NONE); ref19.openForRead(tx, LOCKMODE_NONE); ref20.openForRead(tx, LOCKMODE_NONE); ref21.openForRead(tx, LOCKMODE_NONE); ref22.openForRead(tx, LOCKMODE_NONE); ref23.openForRead(tx, LOCKMODE_NONE); ref24.openForRead(tx, LOCKMODE_NONE); ref25.openForRead(tx, LOCKMODE_NONE); ref26.openForRead(tx, LOCKMODE_NONE); ref27.openForRead(tx, LOCKMODE_NONE); ref28.openForRead(tx, LOCKMODE_NONE); ref29.openForRead(tx, LOCKMODE_NONE); ref30.openForRead(tx, LOCKMODE_NONE); ref31.openForRead(tx, LOCKMODE_NONE); ref32.openForRead(tx, LOCKMODE_NONE); tx.commit(); tx.hardReset(); } durationMs = System.currentTimeMillis() - startMs; System.out.printf("Multiverse> %s is finished in %s ms\n", getName(), durationMs); } } private GammaTxnLong newReadBiasedLongRef(GammaStm stm) { return makeReadBiased(new GammaTxnLong(stm)); } }