package org.hwbot.bench;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.hwbot.bench.prime.ProgressBar;
public class PrimeBenchmark extends Benchmark {
public static final String TIME_SPAN = "timespan";
public static final String SILENT = "silent";
// protected static final int workCountQuick = 1000000;
// protected static final int workCountStability = 2000000;
protected static final int iterations = 100;
protected int batchsize = Integer.valueOf(System.getProperty("batchsize", "16"));
private boolean silent;
public PrimeBenchmark(int threads, ProgressBar progressBar) {
super(threads, progressBar);
}
public PrimeBenchmark(BenchmarkConfiguration config, int threads, ProgressBar progressBar) {
super(config, Integer.valueOf(System.getProperty("threads", String.valueOf(threads))), progressBar);
}
@Override
public String getClient() {
return "HWBOT Prime";
}
@Override
public void warmup() {
silent = false;
if (!silent) {
System.out.print("Warm up phase: ");
}
benchrun(2000l);
if (!silent) {
System.out.println(" done!");
}
}
@Override
public Number benchmark(BenchmarkConfiguration configuration) {
super.config = configuration;
Long timespan = (Long) super.config.getValue(TIME_SPAN);
if (Boolean.TRUE.equals(super.config.getValue(SILENT))) {
this.silent = true;
}
if (!silent) {
System.out.print("Benchmark phase: ");
}
Float benchrun = benchrun(timespan);
if (!silent) {
System.out.println(" done!");
}
return benchrun;
}
public Float benchrun(long timespanInMillis) {
long before = System.currentTimeMillis();
int primeStart = 5;
int iteration = 0;
int brokenWorkers = 0;
int blocksize = threads * batchsize;
int seconds = (int) (timespanInMillis / 1000);
int progressFactor = 100 / seconds;
List<Number> list = Collections.synchronizedList(new ArrayList<Number>());
ThreadFactory tf = new ThreadFactory() {
public Thread newThread(Runnable runnable) {
Thread thread = new Thread(runnable);
thread.setPriority(Thread.MAX_PRIORITY);
return thread;
}
};
ExecutorService exec = Executors.newFixedThreadPool(threads, tf);
List<Future<Void>> workers = new ArrayList<Future<Void>>(blocksize * 2);
long time = getTime();
long endTime = time + timespanInMillis;
int i = 0;
while (getTime() <= endTime) {
// submit work to the svc for execution across the thread pool
i++;
PrimeRunnable worker = new PrimeRunnable(primeStart + i, list);
Future<Void> submit = exec.submit(worker);
workers.add(submit);
if (workers.size() == blocksize * 2) {
ArrayList<Future<Void>> runningWorkers = new ArrayList<Future<Void>>(workers.subList(0, blocksize));
workers = new ArrayList<Future<Void>>(workers.subList(blocksize, blocksize * 2));
for (Future<Void> future : runningWorkers) {
try {
future.get(1, TimeUnit.SECONDS);
long tl = (getTime() - time) / (1000 / progressFactor);
if (tl > iteration) {
iteration++;
if (!silent) {
this.progressBar.setValue(iteration);
}
}
} catch (TimeoutException e) {
System.err.print("x");
brokenWorkers++;
} catch (InterruptedException e) {
e.printStackTrace();
throw new RuntimeException();
} catch (Throwable e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
}
for (Future<Void> future : workers) {
try {
future.get();
} catch (InterruptedException e) {
e.printStackTrace();
throw new RuntimeException(e);
} catch (Throwable e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
this.progressBar.setValue(100);
if (brokenWorkers > 0) {
System.err.println("[UNSTABLE] There were " + brokenWorkers + " broken workers out of " + i);
}
float timeneeded = (getTime() - before) / 1000f;
int primescalculated = list.size();
return (primescalculated / timeneeded);
}
private long getTime() {
return System.currentTimeMillis();
}
public static int getIterations() {
return iterations;
}
@Override
protected void finalize() throws Throwable {
System.out.println("exiting prime benchmark");
super.finalize();
}
}