Gitlab service upgraded. Please report any problems to dl_gitadmin@cs.lth.se

Commit 549c3195 authored by Noric Couderc's avatar Noric Couderc

Merge branch 'applications-refactoring' of...

Merge branch 'applications-refactoring' of https://git.cs.lth.se/noricc/jbrainy into applications-refactoring
parents ff1b58d1 38d8e019
......@@ -9,7 +9,7 @@
// Apply the java plugin to add support for Java
buildscript {
ext.kotlin_version = '1.3.11'
ext.kotlin_version = '1.3.41'
repositories {
mavenCentral()
}
......@@ -21,6 +21,7 @@ buildscript {
plugins {
id 'java'
id 'idea'
id 'org.jetbrains.kotlin.jvm' version "1.3.41"
id 'application' // For running as an app.
// If this doesn't work, update gradle using // $ ./gradlew wrapper
// $ ./gradlew wrapper --gradle-version <version>
......@@ -32,8 +33,6 @@ compileJava {
targetCompatibility = 9
}
apply plugin: 'kotlin'
mainClassName = 'se.lth.cs.Main'
applicationDefaultJvmArgs = ["-Djava.library.path=/usr/lib/x86_64-linux-gnu:./papi-java"]
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -18,9 +18,6 @@ public abstract class Application<T> {
T argument;
// All methods which might be called.
List<Method> allCallableMethods;
private Method[] methodsToCall;
int currentMethodIndex;
......@@ -40,20 +37,6 @@ public abstract class Application<T> {
clearDataStructure(); // TODO: This is a bit odd
// We get the list of methods to run.
Method[] ms = this.getClass().getMethods();
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));
// Argument becomes a new data structure of same class as
// the data structure to test
try {
......@@ -62,13 +45,79 @@ public abstract class Application<T> {
e.printStackTrace();
}
if (allCallableMethods.isEmpty()) { return; }
List<Method> callableMethods = getRunnableMethods();
if (callableMethods.isEmpty()) { return; }
methodsToCall = getRandomTrace(applicationSize, callableMethods);
}
Application(List<String> trace, T structure) {
randomGenerator = new Random();
methodsToCall = new Method[trace.size()];
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))
);
}
}
// TODO: Some copy-paste here
this.applicationSize = trace.size();
this.dataStructure = structure;
this.baseStructureSize = 0;
clearDataStructure();
}
/**
* 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();
methodsToCall[i] = fetchMethod(callableMethods);
}
return 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;
}
Application(int seed, int applicationSize, int baseStructureSize, T structure) {
......@@ -76,11 +125,11 @@ public abstract class Application<T> {
populate(baseStructureSize);
}
protected Method fetchMethod() {
protected Method fetchMethod(List<Method> callableMethods) {
// We select a random method to call.
int i = randomGenerator.nextInt(allCallableMethods.size());
Method selected = allCallableMethods.get(i);
allCallableMethods.add(selected); // We add it back to the list of methods, to make it more likely to be selected!
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;
}
......
......@@ -2,6 +2,7 @@ package se.lth.cs;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
public class CollectionApplication<T extends Collection> extends Application<T> {
......@@ -17,6 +18,10 @@ public class CollectionApplication<T extends Collection> extends Application<T>
super(seed, applicationSize, baseStructureSize, (T) init);
}
public CollectionApplication(List<String> trace, Collection<Integer> init) {
super(trace, (T) init);
}
@Override
public void populate(int numberElements) {
super.populate(numberElements);
......
package se.lth.cs;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
......@@ -18,6 +19,10 @@ public class ListApplication extends CollectionApplication<List<Integer>> {
super(seed, applicationSize, baseStructureSize, init);
}
public ListApplication(List<String> trace, List<Integer> init) {
super(trace, init);
}
public void runAdd2() {
if (dataStructure.isEmpty()) {
dataStructure.add(0, randomGenerator.nextInt());
......
package se.lth.cs;
import java.util.Collection;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.*;
public class MapApplication extends Application<Map<Integer, Integer>> {
......@@ -15,6 +12,10 @@ public class MapApplication extends Application<Map<Integer, Integer>> {
super(seed, applicationSize, baseStructureSize, structure);
}
public MapApplication(List<String> trace, Map<Integer, Integer> init) {
super(trace, init);
}
@Override
public void populate(int numberElements) {
super.populate(numberElements);
......
package se.lth.cs;
import java.util.List;
import java.util.Set;
public class SetApplication extends CollectionApplication<Set<Integer>> {
......@@ -11,4 +12,8 @@ public class SetApplication extends CollectionApplication<Set<Integer>> {
public SetApplication(int seed, int applicationSize, int baseStructureSize, Set<Integer> set) {
super(seed, applicationSize, baseStructureSize, set);
}
public SetApplication(List<String> trace, Set<Integer> init) {
super(trace, init);
}
}
......@@ -210,6 +210,11 @@ open class PapiRunner(counters: CounterSpecification) {
}
}
/**
* Saves a list of feature vectors to a CSV file
* @param vectors The list of feature vectors to save
* @return the text of the file to be saved
*/
fun featuresToCSV(vectors: List<FeatureVector>): String {
if (vectors.isEmpty()) return ""
......@@ -244,10 +249,15 @@ open class PapiRunner(counters: CounterSpecification) {
return "$headerText\n$valuesText"
}
fun processJMHData(numRuns: Int, jmhData: List<JMHProcessor.JMHRecord>): List<FeatureVector> {
return processJMHData(numRuns, jmhData.asSequence())
}
/**
* Transforms a sequence of JMH records to a list of feature vectors,
* by re-generating the application
* @param numRuns number of times each app is deemed to be ran
* @param jmhData the sequence of JMH records
* @return return a list of feature vectors
*/
fun processJMHData(numRuns: Int, jmhData: Sequence<JMHProcessor.JMHRecord>): List<FeatureVector> {
val applications = jmhData.map {
it.generateApplication()!!
......@@ -271,4 +281,14 @@ open class PapiRunner(counters: CounterSpecification) {
aggregates)
}.toList()
}
}
/**
* Transforms a list of JMH records to a list of feature vectors,
* by re-generating the application
* @param numRuns number of times each app is deemed to be ran
* @param jmhData the sequence of JMH records
* @return return a list of feature vectors
*/
fun processJMHData(numRuns: Int, jmhData: List<JMHProcessor.JMHRecord>): List<FeatureVector> {
return processJMHData(numRuns, jmhData.asSequence())
}}
......@@ -309,5 +309,79 @@ public class ApplicationTest {
Assert.assertEquals(app1.methodHistogram(),
app2.methodHistogram());
}
@Test
public void testApplicationTraceGeneration() throws InvocationTargetException, IllegalAccessException {
List<String> trace = List.of(
"runAdd",
"runAdd",
"runSize",
"runGet"
);
ListApplication app = new ListApplication(trace, new ArrayList());
while (app.hasNext()) {
app.invokeCurrentMethod();
app.tick();
}
ListApplication expected = new ListApplication(0, 0, new ArrayList<>());
expected.runAdd();
expected.runAdd();
int s = expected.runSize();
int e = expected.runGet();
Assert.assertEquals(s, app.runSize());
Assert.assertTrue(expected.getDataStructure().contains(e));
Assert.assertTrue(app.getDataStructure().contains(app.runGet()));
}
@Test
public void testSetApplicationTrace() throws InvocationTargetException, IllegalAccessException {
List<String> trace = List.of(
"runAdd",
"runAdd",
"runSize",
"runContains"
);
SetApplication app = new SetApplication(trace, new TreeSet<>());
while (app.hasNext()) {
app.invokeCurrentMethod();
app.tick();
}
SetApplication expected = new SetApplication(0, 0, new TreeSet<>());
expected.runAdd();
expected.runAdd();
int s = expected.runSize();
Assert.assertEquals(s, app.runSize());
}
@Test
public void testMapApplicationTrace() throws InvocationTargetException, IllegalAccessException {
List<String> trace = List.of(
"runPut",
"runPut",
"runSize",
"runGet"
);
MapApplication app = new MapApplication(trace, new HashMap<>());
while (app.hasNext()) {
app.invokeCurrentMethod();
app.tick();
}
MapApplication expected = new MapApplication(0, 0, new HashMap<>());
expected.runPut();
expected.runPut();
int s = expected.runSize();
int e = expected.runGet();
Assert.assertEquals(s, app.runSize());
Assert.assertTrue(expected.getDataStructure().containsValue(e));
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment