Details
diff --git a/src/main/java/br/ufrgs/inf/prosoft/approachescomparison/adapter/CallGraphReader.java b/src/main/java/br/ufrgs/inf/prosoft/approachescomparison/adapter/CallGraphReader.java
index c383207..8eeac6c 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/approachescomparison/adapter/CallGraphReader.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/approachescomparison/adapter/CallGraphReader.java
@@ -10,9 +10,13 @@ import br.ufrgs.inf.prosoft.memoizeit.graph.Node;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -54,10 +58,42 @@ public class CallGraphReader {
return new Graph<>();
}
+ public static Map<String, Set<String>> parseFileToMap(String path) {
+ Map<String, Set<String>> nodeHasLinks = new HashMap<>();
+ try {
+ List<String> lines = Files.readAllLines(Paths.get(path));
+ for (String line : lines) {
+ if (line.charAt(0) != 'M') {
+ continue;
+ }
+ int indexOfSpace = line.indexOf(" ");
+ String callerString = line.substring(2, indexOfSpace);
+ String calleeString = line.substring(indexOfSpace + 4, line.length());
+ callerString = reshapeMethodName(callerString);
+ calleeString = reshapeMethodName(calleeString);
+ Set<String> links = nodeHasLinks.get(callerString);
+ if (links == null) {
+ links = new HashSet<>();
+ nodeHasLinks.put(callerString, links);
+ }
+ links.add(calleeString);
+ }
+ } catch (IOException ex) {
+ Logger.getLogger(CallGraphReader.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ return nodeHasLinks;
+ }
+
private static String reshapeMethodName(String methodName) {
return methodName.substring(0, methodName.indexOf("("))
.replace(":", ".")
.replace("$", ".");
}
+ private static Collection<Node<String>> getRoots(Graph<String> graph) {
+ Collection<Node<String>> roots = new ArrayList<>(graph.getNodes());
+ graph.getEdges().forEach(edge -> roots.remove(edge.getTarget()));
+ return roots;
+ }
+
}
diff --git a/src/main/java/br/ufrgs/inf/prosoft/approachescomparison/adapter/TraceReader.java b/src/main/java/br/ufrgs/inf/prosoft/approachescomparison/adapter/TraceReader.java
index c23268b..468fee0 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/approachescomparison/adapter/TraceReader.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/approachescomparison/adapter/TraceReader.java
@@ -7,6 +7,7 @@ package br.ufrgs.inf.prosoft.approachescomparison.adapter;
import br.ufrgs.inf.prosoft.memoizeit.Method;
import br.ufrgs.inf.prosoft.memoizeit.Occurrence;
+import br.ufrgs.inf.prosoft.memoizeit.Parameter;
import br.ufrgs.inf.prosoft.trace.Trace;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
@@ -38,7 +39,7 @@ public class TraceReader {
Trace trace = gson.fromJson(line, Trace.class);
traces.add(trace);
} catch (JsonSyntaxException e) {
- System.err.println("Malformed Trace");
+ System.err.println("Malformed Trace: " + line);
}
}
} catch (IOException ex) {
@@ -53,9 +54,9 @@ public class TraceReader {
while (!traces.isEmpty()) {
Trace trace = traces.remove(0);
try {
- List<Object> parameters = new ArrayList<>();
+ List<Parameter> parameters = new ArrayList<>();
trace.getParameters().forEach((parameter) -> {
- parameters.add(parameter.getData());
+ parameters.add(new Parameter(parameter.getType(), parameter.getData()));
});
Occurrence occurrence = new Occurrence(trace.getInstance(), trace.getReturn().getData(), parameters, trace.getStartTime(), trace.getEndTime());
try {
diff --git a/src/main/java/br/ufrgs/inf/prosoft/memoizeit/graph/Edge.java b/src/main/java/br/ufrgs/inf/prosoft/memoizeit/graph/Edge.java
new file mode 100644
index 0000000..ea16ecb
--- /dev/null
+++ b/src/main/java/br/ufrgs/inf/prosoft/memoizeit/graph/Edge.java
@@ -0,0 +1,30 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package br.ufrgs.inf.prosoft.memoizeit.graph;
+
+/**
+ *
+ * @author romulo
+ */
+public class Edge<U> {
+
+ private final Node<U> source;
+ private final Node<U> target;
+
+ public Edge(Node<U> source, Node<U> target) {
+ this.source = source;
+ this.target = target;
+ }
+
+ public Node<U> getSource() {
+ return source;
+ }
+
+ public Node<U> getTarget() {
+ return target;
+ }
+
+}
diff --git a/src/main/java/br/ufrgs/inf/prosoft/memoizeit/graph/Graph.java b/src/main/java/br/ufrgs/inf/prosoft/memoizeit/graph/Graph.java
index 9296ec9..1d30440 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/memoizeit/graph/Graph.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/memoizeit/graph/Graph.java
@@ -5,8 +5,12 @@
*/
package br.ufrgs.inf.prosoft.memoizeit.graph;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
/**
*
@@ -28,4 +32,21 @@ public class Graph<U> {
return this.contentHasNode.get(content);
}
+ public Collection<Node<U>> getNodes() {
+ return this.contentHasNode.values();
+ }
+
+ public Collection<Edge<U>> getEdges() {
+ return this.contentHasNode.values().stream()
+ .map(node
+ -> node.getLinks().stream()
+ .map(link -> new Edge<>(node, link))
+ .collect(Collectors.toList()))
+ .reduce(new ArrayList<>(), (a, b) -> {
+ List arrayList = new ArrayList<>(a);
+ arrayList.addAll(b);
+ return arrayList;
+ });
+ }
+
}
diff --git a/src/main/java/br/ufrgs/inf/prosoft/memoizeit/MemoizeIt.java b/src/main/java/br/ufrgs/inf/prosoft/memoizeit/MemoizeIt.java
index fda5a8b..b7b99e9 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/memoizeit/MemoizeIt.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/memoizeit/MemoizeIt.java
@@ -90,15 +90,11 @@ public class MemoizeIt {
}
private void estimateTotalProgramExecution() {
- this.methods.forEach((method) -> {
- this.totalProgramExecution += method.getTotalExecutionTime();
- });
+ this.totalProgramExecution = this.methods.stream().map(method -> method.getTotalExecutionTime()).reduce(Long::sum).get();
}
private void calculateAverageExecutionTime() {
- this.methods.forEach((method) -> {
- this.averageProgramExecution += method.getAverageExecutionTime();
- });
+ this.averageProgramExecution = this.methods.stream().map(method -> method.getAverageExecutionTime()).reduce(Long::sum).get();
this.averageProgramExecution /= this.methods.size();
}
@@ -124,6 +120,10 @@ public class MemoizeIt {
}
}
+ private void removeUnusedFields() {
+ this.methods.forEach(method -> method.removeUnusedFields(this.callGraph.getNode(method.getName())));
+ }
+
// 3.2 input-output profiling
private void refineCandidates() {
refineCandidates(Integer.MAX_VALUE);
@@ -180,7 +180,7 @@ public class MemoizeIt {
}
}
- private Collection<Method> getIndirectCallees(List<Node<String>> visited, String packageName, Node<String> node) {
+ private Collection<Method> getIndirectCallees(List<Node<String>> visited, String rootPackage, Node<String> node) {
Collection<Method> cluster = new ArrayList<>();
Collection<Node<String>> directCallees = node.getLinks();
for (Node<String> directCallee : directCallees) {
@@ -193,11 +193,11 @@ public class MemoizeIt {
.findAny()
.ifPresent((callee) -> {
String calleePackage = callee.getName().substring(0, callee.getName().lastIndexOf("."));
- if (calleePackage.equals(packageName)) {
+ if (calleePackage.equals(rootPackage)) {
cluster.add(callee);
}
});
- cluster.addAll(getIndirectCallees(visited, packageName, directCallee));
+ cluster.addAll(getIndirectCallees(visited, rootPackage, directCallee));
}
return cluster;
}
@@ -207,6 +207,9 @@ public class MemoizeIt {
cluster.add(root);
String rootPackage = root.getName().substring(0, root.getName().lastIndexOf("."));
Node<String> node = this.callGraph.getNode(root.getName());
+ if (node == null) {
+ return cluster;
+ }
visited.add(node);
Collection<Node<String>> directCallees = node.getLinks();
for (Node<String> directCallee : directCallees) {
@@ -214,7 +217,6 @@ public class MemoizeIt {
continue;
}
visited.add(directCallee);
- Map<String, Method> a = null;
this.methods.stream()
.filter(method -> method.getName().equals(directCallee.getContent()))
.findAny()
@@ -315,6 +317,7 @@ public class MemoizeIt {
throw new RuntimeException("Call Graph not set");
}
filterInitialCandidates();
+ removeUnusedFields();
refineCandidatesIteratively();
}
@@ -337,6 +340,7 @@ public class MemoizeIt {
throw new RuntimeException("Call Graph not set");
}
filterInitialCandidates();
+ removeUnusedFields();
refineCandidatesIteratively();
printClusters();
suggestImplementations();
diff --git a/src/main/java/br/ufrgs/inf/prosoft/memoizeit/Method.java b/src/main/java/br/ufrgs/inf/prosoft/memoizeit/Method.java
index d330456..b2b4eb0 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/memoizeit/Method.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/memoizeit/Method.java
@@ -8,6 +8,7 @@ package br.ufrgs.inf.prosoft.memoizeit;
import br.ufrgs.inf.prosoft.memoizeit.cache.CachingPerformance;
import br.ufrgs.inf.prosoft.memoizeit.cache.MultiCache;
import br.ufrgs.inf.prosoft.memoizeit.cache.SingleCache;
+import br.ufrgs.inf.prosoft.memoizeit.graph.Node;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -92,10 +93,8 @@ public class Method {
continue;
}
Occurrence firstOccurrence = entry.getValue().get(0);
- for (Occurrence occurrence : entry.getValue()) {
- if (occurrence.getReturnValue() != null && !occurrence.getReturnValue().equals(firstOccurrence.getReturnValue())) {
- return true;
- }
+ if (entry.getValue().stream().anyMatch((occurrence) -> (occurrence.getReturnValue() != null && !occurrence.getReturnValue().equals(firstOccurrence.getReturnValue())))) {
+ return true;
}
}
return false;
@@ -107,6 +106,14 @@ public class Method {
return potentialHitRatio;
}
+ protected void removeUnusedFields(Node<String> methodNode) {
+ if (methodNode == null) {
+ System.err.println("methodNode null: " + this.name);
+ return;
+ }
+ this.occurrences.stream().forEach(occurrence -> occurrence.removeUnusedFields(methodNode));
+ }
+
protected Map<String, CachingPerformance> simulateCachingStrategies() {
Map<String, CachingPerformance> cachingStrategyHasPerformance = new HashMap<>();
CachingPerformance globalMultiCachePerformance = new CachingPerformance();
diff --git a/src/main/java/br/ufrgs/inf/prosoft/memoizeit/Occurrence.java b/src/main/java/br/ufrgs/inf/prosoft/memoizeit/Occurrence.java
index 7d1e54f..5a7dce4 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/memoizeit/Occurrence.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/memoizeit/Occurrence.java
@@ -6,9 +6,14 @@
package br.ufrgs.inf.prosoft.memoizeit;
import br.ufrgs.inf.prosoft.memoizeit.cache.Cache;
+import br.ufrgs.inf.prosoft.memoizeit.graph.Node;
import br.ufrgs.inf.prosoft.memoizeit.utils.Action;
import br.ufrgs.inf.prosoft.memoizeit.utils.ObjectUtils;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
import java.util.List;
+import java.util.Map;
/**
*
@@ -18,12 +23,12 @@ public class Occurrence {
private final String instance;
private final Object returnValue;
- private final List<Object> parameters;
+ private final List<Parameter> parameters;
private final long startTime;
private final long endTime;
private boolean truncated;
- public Occurrence(String instance, Object returnValue, List<Object> parameters, long startTime, long endTime) {
+ public Occurrence(String instance, Object returnValue, List<Parameter> parameters, long startTime, long endTime) {
this.instance = instance;
this.returnValue = returnValue;
this.parameters = parameters;
@@ -40,7 +45,7 @@ public class Occurrence {
return this.returnValue;
}
- public List<Object> getParameters() {
+ public List<Parameter> getParameters() {
return this.parameters;
}
@@ -58,8 +63,12 @@ public class Occurrence {
this.truncated = true;
};
ObjectUtils.truncateObject(returnValue, depth, onTruncate);
- List<Object> parameters = ObjectUtils.deepCopy(this.parameters);
- ObjectUtils.truncateObject(parameters, depth, onTruncate);
+ List<Parameter> parameters = new ArrayList<>();
+ for (Parameter parameter : this.parameters) {
+ Object parameterView = ObjectUtils.deepCopy(parameter.getData());
+ ObjectUtils.truncateObject(parameterView, depth, onTruncate);
+ parameters.add(new Parameter(parameter.getType(), parameterView));
+ }
Occurrence occurrence = new Occurrence(this.instance, returnValue, parameters, this.startTime, this.endTime);
return occurrence;
}
@@ -74,4 +83,32 @@ public class Occurrence {
}
}
+ private void removeUnusedFields(Map<String, Object> map, String parameterType, Node<String> methodNode) {
+ Iterator<Map.Entry<String, Object>> iterator = map.entrySet().iterator();
+ while (iterator.hasNext()) {
+ Map.Entry<String, Object> entry = iterator.next();
+ String getter = parameterType + ".get" + entry.getKey().substring(0, 1).toUpperCase() + entry.getKey().substring(1);
+ if (!methodNode.getLinks().stream().anyMatch(node -> node.getContent().equals(getter))) {
+ iterator.remove();
+ }
+ }
+
+ }
+
+ protected void removeUnusedFields(Node<String> methodNode) {
+ for (Parameter parameter : this.parameters) {
+ String parameterType = parameter.getType();
+ if (parameter.getData() instanceof Collection) {
+ Collection collection = (Collection) parameter.getData();
+ if (collection.stream().findAny().get() instanceof Map) {
+ Collection<Map<String, Object>> cast = collection;
+ cast.forEach(map -> removeUnusedFields(map, parameterType, methodNode));
+ }
+ } else if (parameter.getData() instanceof Map) {
+ Map<String, Object> map = (Map<String, Object>) parameter.getData();
+ removeUnusedFields(map, parameterType, methodNode);
+ }
+ }
+ }
+
}
diff --git a/src/main/java/br/ufrgs/inf/prosoft/memoizeit/Parameter.java b/src/main/java/br/ufrgs/inf/prosoft/memoizeit/Parameter.java
new file mode 100644
index 0000000..6cb6bed
--- /dev/null
+++ b/src/main/java/br/ufrgs/inf/prosoft/memoizeit/Parameter.java
@@ -0,0 +1,35 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package br.ufrgs.inf.prosoft.memoizeit;
+
+/**
+ *
+ * @author romulo
+ */
+public class Parameter {
+
+ private final String type;
+ private final Object data;
+
+ public Parameter(String type, Object data) {
+ this.type = type;
+ this.data = data;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ @Override
+ public String toString() {
+ return this.data.toString();
+ }
+
+}
diff --git a/src/main/java/br/ufrgs/inf/prosoft/memoizeit/utils/ObjectUtils.java b/src/main/java/br/ufrgs/inf/prosoft/memoizeit/utils/ObjectUtils.java
index 425a7c7..c2493ff 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/memoizeit/utils/ObjectUtils.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/memoizeit/utils/ObjectUtils.java
@@ -22,9 +22,8 @@ public class ObjectUtils {
public static Object truncateObject(Object object, int depth, Action onTruncate) {
if (depth == 0) {
- object = "...";
onTruncate.perform();
- return object;
+ return "...";
}
if (object instanceof Map) {
Map<String, Object> map = (Map<String, Object>) object;