Commit 8ee7fbdb authored by Christoph Reichenbach's avatar Christoph Reichenbach
Browse files

Preparatory refactoring for arbitrary-length trace exec

parent 2e96557d
......@@ -12,9 +12,9 @@ public class ListSyntheticBenchmarkGenerator implements SyntheticBenchmarkGenera
public List<BCBenchmarkPackage<?>> createApplications(int seed, int number, int size) {
List<BCBenchmarkPackage<?>> listSyntheticBenchmarks = new ArrayList<>();
for (int i = 0; i < number; ++i) {
listSyntheticBenchmarks.add(new BCBenchmarkPackage.LIST(seed + i, size, 0, new ArrayList<>()));
listSyntheticBenchmarks.add(new BCBenchmarkPackage.LIST(seed + i, size, 0, new LinkedList<>()));
listSyntheticBenchmarks.add(new BCBenchmarkPackage.LIST(seed + i, size, 0, new Vector<>()));
listSyntheticBenchmarks.add(BCBenchmarkPackage.LIST(seed + i, size, 0, new ArrayList<>()));
listSyntheticBenchmarks.add(BCBenchmarkPackage.LIST(seed + i, size, 0, new LinkedList<>()));
listSyntheticBenchmarks.add(BCBenchmarkPackage.LIST(seed + i, size, 0, new Vector<>()));
}
return listSyntheticBenchmarks;
......
......@@ -10,11 +10,11 @@ public class MapSyntheticBenchmarkGenerator implements SyntheticBenchmarkGenerat
List<BCBenchmarkPackage<?>> mapSyntheticBenchmarks = new ArrayList<>();
for (int i = 0; i < number; ++i) {
mapSyntheticBenchmarks.add(new BCBenchmarkPackage.MAP(seed + i, size, 0, new HashMap<>()));
mapSyntheticBenchmarks.add(new BCBenchmarkPackage.MAP(seed + i, size, 0, new TreeMap<>()));
mapSyntheticBenchmarks.add(new BCBenchmarkPackage.MAP(seed + i, size, 0, new IdentityHashMap<>()));
mapSyntheticBenchmarks.add(new BCBenchmarkPackage.MAP(seed + i, size, 0, new LinkedHashMap<>()));
mapSyntheticBenchmarks.add(new BCBenchmarkPackage.MAP(seed + i, size, 0, new WeakHashMap<>()));
mapSyntheticBenchmarks.add(BCBenchmarkPackage.MAP(seed + i, size, 0, new HashMap<>()));
mapSyntheticBenchmarks.add(BCBenchmarkPackage.MAP(seed + i, size, 0, new TreeMap<>()));
mapSyntheticBenchmarks.add(BCBenchmarkPackage.MAP(seed + i, size, 0, new IdentityHashMap<>()));
mapSyntheticBenchmarks.add(BCBenchmarkPackage.MAP(seed + i, size, 0, new LinkedHashMap<>()));
mapSyntheticBenchmarks.add(BCBenchmarkPackage.MAP(seed + i, size, 0, new WeakHashMap<>()));
}
return mapSyntheticBenchmarks;
......
......@@ -11,11 +11,11 @@ public class SetSyntheticBenchmarkGenerator implements SyntheticBenchmarkGenerat
public List<BCBenchmarkPackage<?>> createApplications(int seed, int number, int size) {
List<BCBenchmarkPackage<?>> setSyntheticBenchmarks = new ArrayList<>();
for (int i = 0; i < number; ++i) {
setSyntheticBenchmarks.add(new BCBenchmarkPackage.SET(seed + i, 0, size, new HashSet<>()));
setSyntheticBenchmarks.add(new BCBenchmarkPackage.SET(seed + i, 0, size, new TreeSet<>()));
setSyntheticBenchmarks.add(new BCBenchmarkPackage.SET(seed + i, 0, size, new LinkedHashSet<>()));
setSyntheticBenchmarks.add(new BCBenchmarkPackage.SET(seed + i, 0, size, new ConcurrentSkipListSet<>()));
setSyntheticBenchmarks.add(new BCBenchmarkPackage.SET(seed + i, 0, size, new CopyOnWriteArraySet<>()));
setSyntheticBenchmarks.add(BCBenchmarkPackage.SET(seed + i, 0, size, new HashSet<>()));
setSyntheticBenchmarks.add(BCBenchmarkPackage.SET(seed + i, 0, size, new TreeSet<>()));
setSyntheticBenchmarks.add(BCBenchmarkPackage.SET(seed + i, 0, size, new LinkedHashSet<>()));
setSyntheticBenchmarks.add(BCBenchmarkPackage.SET(seed + i, 0, size, new ConcurrentSkipListSet<>()));
setSyntheticBenchmarks.add(BCBenchmarkPackage.SET(seed + i, 0, size, new CopyOnWriteArraySet<>()));
}
return setSyntheticBenchmarks;
......
......@@ -88,6 +88,7 @@ public class SyntheticBenchmarkRunner {
try {
for (int i = -numberWarmups; i < numberSamples; ++i) {
app.reset();
long startTime = System.nanoTime();
app.runBenchmark();
long endTime = System.nanoTime();
......@@ -98,6 +99,7 @@ public class SyntheticBenchmarkRunner {
}
} catch (Exception ignored) {
System.out.println("running Application failed");
ignored.printStackTrace();
}
return durations;
......
......@@ -11,9 +11,9 @@ import java.util.List;
* - final simulation state
* - list of all operations
*/
public class BCBenchmarkInfo<S> {
public final class BCBenchmarkInfo<S> {
private BCBenchmark benchmark;
private ArrayList<String> op_names = new ArrayList<>();
private List<String> op_names = new ArrayList<>();
private S state;
public
......@@ -36,6 +36,11 @@ public class BCBenchmarkInfo<S> {
return this.op_names;
}
public void
setTrace(List<String> trace) {
this.op_names = trace;
}
public BCBenchmark
getBenchmark() {
return this.benchmark;
......
......@@ -20,6 +20,8 @@ public abstract class BCBenchmarkOp<S> {
protected String method_name;
protected List<BCArg<S>> args;
private BCType return_type;
private List<String> method_aliases = new ArrayList<String>();
private List<String> method_void_aliases = new ArrayList<String>();
/**
* An operation to benchmark
......@@ -39,6 +41,7 @@ public abstract class BCBenchmarkOp<S> {
this.is_interface = is_interface;
this.method_name = method_name;
this.return_type = returntype;
this.method_aliases.add(method_name);
this.args = new ArrayList<BCArg<S>>();
for (BCArg<?> arg : args) {
BCArg<S> carg = (BCArg<S>) arg;
......@@ -46,6 +49,26 @@ public abstract class BCBenchmarkOp<S> {
}
}
// add equivalent method name
public BCBenchmarkOp
addAlias(String aliasname) {
this.method_aliases.add(aliasname);
return this;
}
public List<String>
getAliases() { return this.method_aliases; }
// add equivalent method name
public BCBenchmarkOp
addVoidAlias(String aliasname) {
this.method_void_aliases.add(aliasname);
return this;
}
public List<String>
getVoidAliases() { return this.method_void_aliases; }
public Method
getReflectionMethod(Class<?> basetype) {
Class<?>[] argtypes = new Class<?>[args.size()];
......
......@@ -4,29 +4,127 @@ import org.openjdk.jmh.infra.Blackhole;
import java.util.stream.Stream;
import java.util.stream.Collectors;
/**
* Packaged benchmark with datastructure, for easy re-running
*/
public abstract class BCBenchmarkPackage<T> {
public class BCBenchmarkPackage<T> {
private static int unique_ids_counter = 0; // for BCBenchStep
public static final int MAX_TRACE_LENGTH = 3; // max number of individual entries permitted
private static final String GENTYPE_SYNTH = "Synth";
private static final String GENTYPE_TRACE = "Trace:"; // FIXME: for trace generation later
/**
* For simulating traces that are too long, we break them into several BCBenchSteps.
*/
private class BCBenchStep {
boolean use_global_datastructure_size;
int uid = unique_ids_counter++;
int trace_size;
int seed;
BenchmarkGenerator<T> generator = null;
MethodSelectionStrategy.Trace trace_method_selector = null; // only used for GENTYPE_TRACE
BCBenchmarkInfo<T> benchinfo;
public BCBenchStep(int tsize, int sd, boolean dsize_global) {
this.seed = sd;
this.trace_size = tsize;
this.use_global_datastructure_size = dsize_global;
}
public BCBenchStep
setMethodSelector(MethodSelectionStrategy.Trace strat) {
this.trace_method_selector = strat;
if (this.generator != null) {
this.generator.setMethodSelectionStrategy(strat);
}
return this;
}
// WARNING: must be called in the right order, during our first pass when doing prepareBenchmark
public void
initGenerator() {
if (this.generator == null) {
int ds_size = this.use_global_datastructure_size
? datastructure_size
: gen.getSize(datastructure);
this.generator = gen.makeGenerator(ds_size);
this.generator.overrideSimulationState(datastructure); // dangerous!
if (this.trace_method_selector != null) {
this.generator.setMethodSelectionStrategy(this.trace_method_selector);
}
}
}
// WARNING: must be called in the right order, since we rely on
// BCBenchmarkPackage.this.datastructure to be in the correct simulation stetae!
public void
prepareBenchmark() {
this.benchinfo = this.generator.gen("TraceX_" + this.uid,
this.trace_size, this.seed, this.seed);
}
public void
runBenchmark() {
this.benchinfo.getBenchmark().run(blackhole, datastructure);
}
public void
clearAll() {
this.benchinfo = null;
}
public void
reset() {
if (this.trace_method_selector != null) {
this.trace_method_selector.reset();
}
}
public int
getMissedMethods() {
if (this.trace_method_selector == null) {
return 0;
}
return this.trace_method_selector.getMisses();
}
}
protected String generation_type;
protected T datastructure;
protected int seed;
protected int trace_size;
protected int datastructure_size;
protected String generation_type;
protected BenchmarkGenerator<T> gen;
protected BCGen<T> gen;
protected Blackhole blackhole = new Blackhole("Today's password is swordfish. I understand instantiating Blackholes directly is dangerous.");
protected BCBenchmarkInfo benchinfo = null;
protected MethodSelectionStrategy.Trace trace_method_selector = null; // only used for GENTYPE_TRACE
List<BCBenchStep> bench_steps = new ArrayList<BCBenchStep>();
protected BCBenchmarkInfo<T> combined_benchinfo = null;
private void
setupBenchmarksIfNeeded() {
if (this.combined_benchinfo == null) {
List<String> trace = new ArrayList<>();
this.clearDatastructure();
// the datastructure will carry over across states:
for (BCBenchStep step : this.bench_steps) {
step.initGenerator();
step.prepareBenchmark();
trace.addAll(step.benchinfo.getTrace());
}
this.combined_benchinfo = new BCBenchmarkInfo<T>(this.datastructure);
this.combined_benchinfo.setTrace(trace);
}
}
public BCBenchmarkInfo
getBenchmarkInfo() {
if (this.benchinfo == null) {
this.benchinfo = this.gen.gen("", this.trace_size, this.seed, this.seed);
}
return this.benchinfo;
this.setupBenchmarksIfNeeded();
return this.combined_benchinfo;
}
public BCBenchmark
......@@ -75,14 +173,15 @@ public abstract class BCBenchmarkPackage<T> {
*/
public int
getMissedMethods() {
if (this.trace_method_selector == null) {
return 0;
int count = 0;
for (BCBenchStep step : this.bench_steps) {
count += step.getMissedMethods();
}
return this.trace_method_selector.getMisses();
return count;
}
public BCBenchmarkPackage(int seed, int trace_size, int datastructure_size, T target,
BenchmarkGenerator<T> gen) {
BCGen<T> gen) {
this.generation_type = GENTYPE_SYNTH;
this.datastructure = target;
this.seed = seed;
......@@ -92,21 +191,28 @@ public abstract class BCBenchmarkPackage<T> {
if (gen == null) {
throw new RuntimeException("generator missing");
}
this.bench_steps.add(new BCBenchStep(trace_size,
seed,
true /* use configured datastructure size */));
}
public BCBenchmarkPackage(String trace_key, List<String> methods, T target,
BenchmarkGenerator<T> gen) {
BCGen<T> gen) {
this.generation_type = GENTYPE_TRACE + trace_key;
this.datastructure = target;
this.seed = 0;
this.trace_size = methods.size();
this.datastructure_size = 0;
this.gen = gen;
this.trace_method_selector = MethodSelectionStrategy.fromTrace(methods);
if (gen == null) {
throw new RuntimeException("generator missing");
}
gen.setMethodSelectionStrategy(this.trace_method_selector);
// FIXME: break up as needed
this.bench_steps.add(new BCBenchStep(trace_size,
seed,
false /* infer datastructure size */)
.setMethodSelector(MethodSelectionStrategy.fromTrace(methods)));
}
......@@ -154,89 +260,185 @@ public abstract class BCBenchmarkPackage<T> {
return this.datastructure;
}
public void
reset() {
this.reset(this.datastructure_size);
}
public void
reset(int size) {
if (this.trace_method_selector != null) {
this.trace_method_selector.reset();
// if (this.trace_method_selector != null) {
// this.trace_method_selector.reset();
// }
for (BCBenchStep step : this.bench_steps) {
step.reset();
}
this.clearAll();
this.gen.fill(this.datastructure, size);
this.benchinfo = null; // ensure that we generate a fresh benchmark
this.benchinfo = this.getBenchmarkInfo();
this.combined_benchinfo = null;
this.setupBenchmarksIfNeeded();
//System.err.println("Pondering FILL" + size);
if (this.bench_steps.size() == 1) {
//System.err.println("FILLing for size " + size);
this.bench_steps.get(0).generator.fill(this.datastructure, size);
} else if (size > 0) {
throw new RuntimeException("Resetting with nonzero size not supported for traces!");
}
}
/**
* Must be run after a reset (which should not be included in the timing!)
*/
public void runBenchmark() {
this.getBenchmark().run(this.blackhole, this.datastructure);
for (BCBenchStep step : this.bench_steps) {
step.runBenchmark();
}
}
public void
clearAll() {
this.blackhole.evaporate("Yes, I am Stephen Hawking, and know a thing or two about black holes.");
this.clear();
this.benchinfo = null;
this.clearDatastructure();
this.combined_benchinfo = null;
for (BCBenchStep step : this.bench_steps) {
step.clearAll();
}
}
protected abstract void
clear();
public static class LIST extends BCBenchmarkPackage<java.util.List<Object>> {
public
LIST(int seed, int trace_size, int datastructure_size, java.util.List<?> target) {
super(seed, trace_size, datastructure_size, (java.util.List<Object>)target,
new ListBenchmarkGenerator(datastructure_size));
}
protected void
clearDatastructure() {
this.gen.clear(this.datastructure);
}
public
LIST(String trace_key, java.util.List<String> methods, java.util.List<?> target) {
super(trace_key, methods, (List<Object>)target,
new ListBenchmarkGenerator(0));
}
// ----------------------------------------
// container-specific bits
@Override
protected void
clear() {
datastructure.clear();
}
public interface BCGen<S> {
public void clear(S ds);
public BenchmarkGenerator<S> makeGenerator(int initial_datastructure_size);
public int getSize(S ds);
/**
* Name of the short interface to be benchmarked interface (e.g., "List")
*/
public String
getInterfaceIdentifier();
}
public static class SET extends BCBenchmarkPackage<java.util.Set<Object>> {
public
SET(int seed, int trace_size, int datastructure_size, java.util.Set<?> target) {
super(seed, trace_size, datastructure_size, (java.util.Set<Object>)target,
new SetBenchmarkGenerator(datastructure_size));
}
public
SET(String trace_key, java.util.List<String> methods, Set<?> target) {
super(trace_key, methods, (Set<Object>)target,
new SetBenchmarkGenerator(0));
}
// lists --------------------
private static final BCGen<List<Object>> BCGenLIST = new BCGen<List<Object>>() {
@Override
public BenchmarkGenerator<List<Object>>
makeGenerator(int ds_size) {
return new ListBenchmarkGenerator(ds_size);
}
@Override
public void
clear(List<Object> ds) {
ds.clear();
}
@Override
public int
getSize(List<Object> ds) {
return ds.size();
}
@Override
public String
getInterfaceIdentifier() {
return "List";
}
};
public static BCBenchmarkPackage<List<Object>>
LIST(int seed, int trace_size, int datastructure_size, java.util.List<?> target) {
return new BCBenchmarkPackage<List<Object>>(seed, trace_size, datastructure_size, (java.util.List<Object>)target,
BCGenLIST);
}
@Override
protected void
clear() {
datastructure.clear();
}
public static BCBenchmarkPackage<List<Object>>
LIST(String trace_key, java.util.List<String> methods, java.util.List<?> target) {
return new BCBenchmarkPackage<List<Object>>(trace_key, methods, (List<Object>)target,
BCGenLIST);
}
public static class MAP extends BCBenchmarkPackage<java.util.Map<Object, Object>> {
public
MAP(int seed, int trace_size, int datastructure_size, java.util.Map<?, ?> target) {
super(seed, trace_size, datastructure_size, (Map<Object, Object>) target,
new MapBenchmarkGenerator(datastructure_size));
}
// sets --------------------
private static final BCGen<Set<Object>> BCGenSET = new BCGen<Set<Object>>() {
@Override
public BenchmarkGenerator<Set<Object>>
makeGenerator(int ds_size) {
return new SetBenchmarkGenerator(ds_size);
}
@Override
public void
clear(Set<Object> ds) {
ds.clear();
}
@Override
public int
getSize(Set<Object> ds) {
return ds.size();
}
@Override
public String
getInterfaceIdentifier() {
return "Set";
}
};
public static BCBenchmarkPackage<Set<Object>>
SET(int seed, int trace_size, int datastructure_size, java.util.Set<?> target) {
return new BCBenchmarkPackage<Set<Object>>(seed, trace_size, datastructure_size, (java.util.Set<Object>)target,
BCGenSET);
}
public
MAP(String trace_key, java.util.List<String> methods, java.util.Map<?, ?> target) {
super(trace_key, methods, (Map<Object,Object>)target,
new MapBenchmarkGenerator(0));
}
public static BCBenchmarkPackage<Set<Object>>
SET(String trace_key, java.util.List<String> methods, java.util.Set<?> target) {
return new BCBenchmarkPackage<Set<Object>>(trace_key, methods, (Set<Object>)target,
BCGenSET);
}
@Override
protected void
clear() {
datastructure.clear();
}
// maps --------------------
private static final BCGen<Map<Object, Object>> BCGenMAP = new BCGen<Map<Object, Object>>() {
@Override
public BenchmarkGenerator<Map<Object, Object>>
makeGenerator(int ds_size) {
return new MapBenchmarkGenerator(ds_size);
}
@Override
public void
clear(Map<Object, Object> ds) {
ds.clear();
}
@Override
public int
getSize(Map<Object, Object> ds) {
return ds.size();
}
@Override
public String
getInterfaceIdentifier() {
return "Map";
}
};
public static BCBenchmarkPackage<Map<Object, Object>>
MAP(int seed, int trace_size, int datastructure_size, java.util.Map<?,?> target) {
return new BCBenchmarkPackage<Map<Object, Object>>(seed, trace_size, datastructure_size, (java.util.Map<Object, Object>)target,
BCGenMAP);
}
public static BCBenchmarkPackage<Map<Object, Object>>
MAP(String trace_key, java.util.List<String> methods, java.util.Map<?,?> target) {
return new BCBenchmarkPackage<Map<Object, Object>>(trace_key, methods, (Map<Object, Object>)target,
BCGenMAP);
}
}
......@@ -32,8 +32,8 @@ public abstract class BenchmarkGenerator<S> {
public static int MAX_CALLS_PER_RUNNER = 8192;
// write generated benchmarks to file for debugging?
//private final String WRITE_BENCHMARK = "/tmp/C.class";
private final String WRITE_BENCHMARK = null;
private final String WRITE_BENCHMARK = "/tmp/C.class";
//private final String WRITE_BENCHMARK = null;
protected Random random = null;
......@@ -43,6