Commit 0eab444e authored by Christoph Reichenbach's avatar Christoph Reichenbach
Browse files

Fixed nine tests

parent 018ff9aa
package se.lth.cs;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
public abstract class CollectionSyntheticBenchmark<T extends Collection> extends SyntheticBenchmark<T> {
CollectionSyntheticBenchmark(int seed, int applicationSize, Collection structure) {
super(seed, applicationSize, (T) structure);
}
public CollectionSyntheticBenchmark(int seed, int applicationSize, int baseStructureSize, Collection<Integer> init) {
super(seed, applicationSize, baseStructureSize, (T) init);
}
public CollectionSyntheticBenchmark(String ident, List<String> trace, Collection<Integer> init) {
super(ident, trace, (T) init);
}
public CollectionSyntheticBenchmark(String ident, int seed, List<String> trace, Collection init) {
super(ident, seed, trace, (T) init);
}
@Override
protected void populateArgument(int numberElements, Random elementGenerator) {
// We add random numbers to the argument for addAll(Collection)
elementGenerator.ints(numberElements).forEach((i) -> argument.add(i));
}
@Override
public void populate(int numberElements) {
super.populate(numberElements);
randomGenerator = new Random(seed);
randomGenerator.ints(numberElements).forEach((i) -> dataStructure.add(i));
}
@Override
public void clearDataStructure() {
dataStructure.clear();
}
public int generateIndex() {
return randomGenerator.nextInt(dataStructure.size());
}
public boolean runAdd() { return dataStructure.add(randomGenerator.nextInt()); }
public boolean runAddAll() { return dataStructure.addAll(argument); }
public void runClear() { dataStructure.clear(); }
public boolean runContains() {
return dataStructure.contains(randomGenerator.nextInt());
}
public boolean runContainsAll() {
return dataStructure.containsAll(argument);
}
public boolean runEquals() {
return dataStructure.equals(randomGenerator.ints(100)); // TODO: Read from configuration
}
public int runHashCode() { return dataStructure.hashCode(); }
public boolean runIsEmpty() { return dataStructure.isEmpty(); }
public Iterator runIterator() { return dataStructure.iterator(); }
public boolean runRemove() {
if (dataStructure.isEmpty()) {
return false;
}
return dataStructure.remove((Object) randomGenerator.nextInt());
}
public boolean runRemoveAll() { return dataStructure.removeAll(argument); }
public boolean runRetainAll() {
return dataStructure.retainAll(argument);
}
public int runSize() { return dataStructure.size(); }
public Object[] runToArray() {
return dataStructure.toArray();
}
public Object[] runToArray2() {
Integer[] array = new Integer[3];
return dataStructure.toArray(array);
}
}
package se.lth.cs;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class ListSyntheticBenchmark extends CollectionSyntheticBenchmark<List<Integer>> {
public ListSyntheticBenchmark(int seed,
int applicationSize,
List<Integer> init) {
super(seed, applicationSize, init);
}
public ListSyntheticBenchmark(int seed,
int applicationSize,
int baseStructureSize,
List<Integer> init) {
super(seed, applicationSize, baseStructureSize, init);
}
public ListSyntheticBenchmark(String ident, int seed, List<String> trace, List init) {
super(ident, seed, trace, init);
}
@Override
public String getInterfaceIdentifier() {
return "List";
}
/**
* Creates a list applications with the random generator set to a specific seed.
* @param ident an identifier for the trace
* @param trace
* @param init
*/
public ListSyntheticBenchmark(String ident, List<String> trace, List<Integer> init) {
super(ident, trace, init);
}
public void runAdd2() {
if (dataStructure.isEmpty()) {
dataStructure.add(0, randomGenerator.nextInt());
return;
}
dataStructure.add(generateIndex(), randomGenerator.nextInt());
}
public boolean runAddAll2() {
if (dataStructure.isEmpty()) {
return dataStructure.addAll(0, argument);
}
return dataStructure.addAll(generateIndex(), argument);
}
public Integer runRemove2() {
if (dataStructure.isEmpty()) {
return null;
}
return dataStructure.remove(generateIndex());
}
public void runSort() {
dataStructure.sort(Integer::compareTo);
}
public Integer runGet() {
if (dataStructure.isEmpty()) {
return null;
}
return dataStructure.get(generateIndex());
}
public int runIndexOf() {
return dataStructure.indexOf(randomGenerator.nextInt());
}
public int runLastIndexOf() {
return dataStructure.lastIndexOf(randomGenerator.nextInt());
}
public ListIterator<Integer> runListIterator() {
return dataStructure.listIterator();
}
public ListIterator<Integer> runListIterator2() {
if (dataStructure.isEmpty()) {
return null;
}
return dataStructure.listIterator(generateIndex());
}
public Integer runSet() {
if (dataStructure.isEmpty()) {
return null;
}
return dataStructure.set(generateIndex(), randomGenerator.nextInt());
}
public List<Integer> runSubList() {
if (dataStructure.isEmpty()) {
return null;
}
int a = generateIndex();
int b = generateIndex();
return dataStructure.subList(Math.min(a, b), Math.max(a, b));
}
}
package se.lth.cs;
import java.util.*;
public class MapSyntheticBenchmark extends SyntheticBenchmark<Map<Integer, Integer>> {
public MapSyntheticBenchmark(int seed, int applicationSize, Map<Integer, Integer> structure) {
super(seed, applicationSize, structure);
}
public MapSyntheticBenchmark(int seed, int applicationSize, int baseStructureSize, Map<Integer, Integer> structure) {
super(seed, applicationSize, baseStructureSize, structure);
}
public MapSyntheticBenchmark(String ident, List<String> trace, Map<Integer, Integer> init) {
super(ident, trace, init);
}
@Override
protected void populateArgument(int numberElements, Random elementGenerator) {
for (int i = 0; i < numberElements; ++i) {
int key = elementGenerator.nextInt();
int value = elementGenerator.nextInt();
argument.put(key, value);
}
}
public MapSyntheticBenchmark(String ident, int seed, List<String> trace, Map<Integer, Integer> structure) {
super(ident, seed, trace, structure);
}
@Override
public void populate(int numberElements) {
super.populate(numberElements);
clearDataStructure();
randomGenerator = new Random(seed);
for (int i = 0; i < numberElements; ++i) {
int k = generateIndex();
int v = randomGenerator.nextInt();
dataStructure.put(k, v);
}
}
@Override
protected void clearDataStructure() {
dataStructure.clear();
}
public void runClear() { dataStructure.clear(); }
public boolean runContainsKey() {
return dataStructure.containsKey(generateIndex()); }
public boolean runContainsValue() {
return dataStructure.containsValue(randomGenerator.nextInt()); }
public Set<Map.Entry<Integer, Integer>> runEntrySet() { return dataStructure.entrySet(); }
public boolean runEquals() { return dataStructure.equals(argument); }
public Integer runGetObject() { return dataStructure.get(generateIndex()); }
public int runHashCode() { return dataStructure.hashCode(); }
public boolean runIsEmpty() { return dataStructure.isEmpty(); }
public Set<Integer> runKeySet() { return dataStructure.keySet(); }
public Integer runPut() {
return dataStructure.put(
generateIndex(),
randomGenerator.nextInt());
}
public void runPutAll() {
dataStructure.putAll(argument);
}
public Integer runRemove2() {
return dataStructure.remove(generateIndex()); }
public int runSize() { return dataStructure.size(); }
public Collection<Integer> runValues() { return dataStructure.values(); }
@Override
public int generateIndex() {
return randomGenerator.nextInt(2 * dataStructure.size() + 1);
}
@Override
public String getInterfaceIdentifier() {
return "Map";
}
}
package se.lth.cs;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
public class SetSyntheticBenchmark extends CollectionSyntheticBenchmark<Set<Integer>> {
public SetSyntheticBenchmark(int seed, int applicationSize, Set<Integer> set) {
super(seed, applicationSize, set);
}
public SetSyntheticBenchmark(int seed, int applicationSize, int baseStructureSize, Set<Integer> set) {
super(seed, applicationSize, baseStructureSize, set);
}
public SetSyntheticBenchmark(String ident, int seed, List<String> trace, Set<Integer> set) {
super(ident, seed, trace, set);
}
@Override
public String getInterfaceIdentifier() {
return "Set";
}
public SetSyntheticBenchmark(String ident, List<String> trace, Set<Integer> init) {
super(ident, trace, init);
}
}
package se.lth.cs;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* An application, meaning "a generated application"
*/
public abstract class SyntheticBenchmark<T> {
/**
* An enum for keeping track of
* whether the plan of the benchmark was generated
* or if it was loaded from a trace.
*/
GenerationType generationType;
Random randomGenerator;
T dataStructure;
T argument;
private Method[] methodsToCall;
int currentMethodIndex;
long seed;
int benchmarkSize;
int baseStructureSize;
SyntheticBenchmark(int seed, int benchmarkSize, T structure) {
this.seed = seed;
this.randomGenerator = new Random(seed);
this.generationType = new SynthGenerationType();
this.benchmarkSize = benchmarkSize;
List<Method> callableMethods = getRunnableMethods();
if (callableMethods.isEmpty()) { return; }
methodsToCall = getRandomTrace(benchmarkSize, callableMethods);
initialize(structure);
}
SyntheticBenchmark(String identifier, List<String> trace, T structure) {
this.randomGenerator = new Random();
this.methodsToCall = new Method[trace.size()];
this.generationType = new TraceGenerationType(identifier);
List<Method> callableMethods = getRunnableMethods();
for(int i = 0; i < trace.size(); ++i) {
int finalI = i;
Optional<Method> method = callableMethods.stream()
.filter((m) -> m.getName().equals(trace.get(finalI)))
.findFirst();
if (method.isPresent()) {
methodsToCall[i] = method.get();
} else {
throw new IllegalArgumentException(
String.format("Method '%s' is not available to use", trace.get(finalI))
);
}
}
initialize(structure);
}
SyntheticBenchmark(String identifier, long seed, List<String> trace, T structure) {
this(identifier, trace, structure);
this.seed = seed;
this.randomGenerator.setSeed(seed);
}
/**
* Initialized the data structure and potential arguments for the
* application.
* @param structure
*/
private void initialize(T structure) {
this.dataStructure = structure;
this.baseStructureSize = 0;
clearDataStructure();
// Argument becomes a new data structure of same class as
// the data structure to test
try {
argument = (T) dataStructure.getClass().newInstance();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
populateArgument(100, new Random(seed));
}
/**
* A method to create the "argument" data structure which will be used
* in "putAll", "addAll", etc.
* Takes a separate RNG to avoid interfering with the previous benchmarks
* @param numberElements
* @param elementGenerator
*/
protected abstract void populateArgument(int numberElements, Random elementGenerator);
/**
* Generates a random sequence of method calls
* @param applicationSize the length of the sequence
* @param allCallableMethods the list of runnable methods to pick from
* @return an array of methods to be run
*/
private Method[] getRandomTrace(int applicationSize, List<Method> allCallableMethods) {
methodsToCall = new Method[applicationSize];
currentMethodIndex = 0;
List<Method> callableMethods = new ArrayList<>(allCallableMethods);
for(int i = 0; i < applicationSize; ++i) {
methodsToCall[i] = fetchMethod(callableMethods);
}
return methodsToCall;
}
/**
* The public version of the method above, returns the list of methods that will be called in application
* @return a list of the methods that will be run
*/
public List<Method> getTrace() {
return Arrays.asList(methodsToCall);
}
/**
* Gets the list of runnable methods for the application
* (the methods whose name starts with "run")
* sorted by name.
* @return the list of runnable methods for the application
*/
private List<Method> getRunnableMethods() {
// We get the list of methods to run.
Method[] ms = this.getClass().getMethods();
List<Method> allCallableMethods = new ArrayList<>();
for (Method m : ms) {
if (m.getName().startsWith("run") && !m.getName().equals("runMethod")) {
allCallableMethods.add(m);
}
}
// VERY IMPORTANT
// The order of "ms" above is not specified.
// If no sorting happens then the order is non-deterministic anyway!
allCallableMethods.sort(Comparator.comparing(Method::getName));
return allCallableMethods;
}
SyntheticBenchmark(int seed, int benchmarkSize, int baseStructureSize, T structure) {
this(seed, benchmarkSize, structure);
populate(baseStructureSize);
}
protected Method fetchMethod(List<Method> callableMethods) {
// We select a random method to call.
int i = randomGenerator.nextInt(callableMethods.size());
Method selected = callableMethods.get(i);
callableMethods.add(selected); // We add it back to the list of me to make it more likely to be selected!
return selected;
}
public boolean hasNext() {
return currentMethodIndex < methodsToCall.length;
}
public void tick() {
currentMethodIndex++;
}
public Object invokeCurrentMethod() throws InvocationTargetException, IllegalAccessException {
return methodsToCall[currentMethodIndex].invoke(this);
}
// Overridden by the implementation classes.
public void populate(int numberElements) {
baseStructureSize = numberElements;
}
/**
* Resets the datastructure to its state before running the benchmark
* @param baseNumberElements: The number of elements the data structure should contain
*/
public void reset(int baseNumberElements) {
randomGenerator = new Random(seed);
currentMethodIndex = 0;
clearDataStructure();
populate(baseNumberElements);
}
protected abstract void clearDataStructure();
abstract public int generateIndex();
public T getDataStructure() { return dataStructure; }
public String getDataStructureName() { return dataStructure.getClass().getCanonicalName(); }
public String getDataStructureSimpleName() { return dataStructure.getClass().getSimpleName(); }
public long getSeed() { return seed; }
public int getBaseDataStructureSize() { return baseStructureSize; }
public String getSeedString() { return Long.toString(seed); }
public Map<String, Long> methodHistogram() {
Stream<Method> l = Arrays.stream(methodsToCall);
return l.collect(Collectors.groupingBy(
x -> x.getName(),
Collectors.counting()));
}
public Map<String, Double> methodNormalizedHistogram() {
Map<String, Long> histogram = methodHistogram();
Map<String, Double> normalizedHistogram = new HashMap<>();
for (String method : histogram.keySet()) {
double normalizedCount = histogram.get(method) / (double) getSize();
normalizedHistogram.put(method, normalizedCount);
}
return normalizedHistogram;
}
public int getSize() { return methodsToCall.length; }
/**
* A Function which returns "LIST" for list benchmarks,
* "MAP" for Map benchmarks, and "SET" for Set benchmarks.
* @return
*/
abstract public String getInterfaceIdentifier();
/**
* A function providing a unique indentifier for a generated benchmarks
* plan, which is the sequence of methods to be executed.
* @return A plan unique ID.
*/
public String getPlanIdentifier() {
return String.format("%s:%d:%d:%s",
generationType.getIdentifier(),
this.seed,
this.benchmarkSize,
this.getInterfaceIdentifier());
}
/**
* A function returning a unique indentifier for the generated benchmark
* which is the idenfitier for the plan, with additional information about the
* collection that was used.
* @return An benchmark unique ID.