package me.brandonc.benchmark;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import me.brandonc.benchmark.exception.OperationException;
public class BenchmarkTask<T> {
private ExecutorService service;
private Context<T> context;
private Action<T> action;
public BenchmarkTask(ExecutorService service, Context<T> context, Action<T> action) {
this.service = service;
this.context = context;
this.action = action;
}
public void start() {
try {
Workload workload = context.getWorkload();
CyclicBarrier barrier = new CyclicBarrier(workload.getConcurrencyLevel() + 1);
int requestCount = workload.getRequestCount();
int concurrencyLevel = workload.getConcurrencyLevel();
// CompositionAction may contain many executions per action
int executionsPerAction = action.getExecutions();
if (requestCount % concurrencyLevel == 0 && (requestCount / concurrencyLevel) % executionsPerAction == 0) {
// fairness execute action on each thread
int executionsPerWorker = requestCount / concurrencyLevel;
for (int i = 0; i < concurrencyLevel; i++) {
service.execute(new Worker<T>(i * executionsPerWorker, i * executionsPerWorker + executionsPerWorker, context, action, barrier));
}
} else {
if (requestCount % executionsPerAction == 0) {
// some worker run more action
int additionActions = (requestCount / executionsPerAction) % concurrencyLevel;
int averageExecutionPerWorker = (requestCount - additionActions * executionsPerAction) / concurrencyLevel;
for (int i = 0; i < requestCount;) {
int executions = averageExecutionPerWorker;
if (additionActions > 0) {
executions += executionsPerAction;
additionActions--;
}
service.execute(new Worker<T>(i, i + executions, context, action, barrier));
i = i + executions;
}
} else {
throw new IllegalArgumentException("requestCount:" + requestCount + " can't completely share at action:" + action.getName());
}
}
barrier.await(); // start benchmark
long start = System.currentTimeMillis();
barrier.await(); // end benchmark
long elapsed = System.currentTimeMillis() - start;
float tps = workload.getRequestCount() / (elapsed / 1000f);
float dps = workload.getRequestCount() * workload.getDataSize() / 1024 / 1024 / (elapsed / 1000f);
System.out.printf("Method: %16s \tThreads: %d \tDataSize: %d \tRequsetCount: %d \tTPS: %.1f \tMB/sec: %.3f", action.getName(), workload.getConcurrencyLevel(), workload.getDataSize(),
workload.getRequestCount(), tps, dps);
System.out.println();
} catch (InterruptedException e) {
throw new OperationException(e);
} catch (BrokenBarrierException e) {
throw new OperationException(e);
}
}
}