package ddth.dasp.test.utils; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; import com.yammer.metrics.Metrics; import com.yammer.metrics.core.Histogram; public class Benchmark { private final Operation operation; private final int concurrentLevel; private final int numberOfRun; private final CyclicBarrier barrier; private final Histogram histogram; public Benchmark(Operation operation, int numberOfRun, int concurrentLevel) { this.operation = operation; this.concurrentLevel = concurrentLevel; this.numberOfRun = numberOfRun; this.barrier = new CyclicBarrier(concurrentLevel + 1); this.histogram = Metrics.newHistogram(Benchmark.class, "operation-histogram" + System.nanoTime()); } private class Worker implements Runnable { final int first; final int length; public Worker(int first, int length) { this.first = first; this.length = length; } @Override public void run() { for (int i = 0; i < length; i++) { long before = System.currentTimeMillis(); operation.run(first + i); histogram.update(System.currentTimeMillis() - before); } try { barrier.await(); } catch (InterruptedException e) { throw new RuntimeException(e); } catch (BrokenBarrierException e) { throw new RuntimeException(e); } } } public BenchmarkResult run() { int opsPerWorker = (int) Math.floor(numberOfRun / concurrentLevel); long before = System.currentTimeMillis(); for (int i = 0; i < concurrentLevel; i++) { int first = i * opsPerWorker; int length = opsPerWorker; if (first + length > numberOfRun) length = numberOfRun - first; new Thread(new Worker(first, length)).start(); } try { barrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } long totalTime = System.currentTimeMillis() - before; return new BenchmarkResult(numberOfRun, totalTime, histogram); } }