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 d9a5bfc..73129d1 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,8 +10,6 @@ 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.Map;
@@ -31,28 +29,29 @@ public class CallGraphReader {
public static Graph<String> parseFile(String path) {
try {
Map<String, Node<String>> callHasNode = new HashMap<>();
- Stream<String> lines = Files.lines(Paths.get(path));
- lines.forEach(line -> {
- if (line.charAt(0) != 'M') {
- return;
- }
- int indexOfSpace = line.indexOf(" ");
- String callerString = line.substring(2, indexOfSpace);
- String calleeString = line.substring(indexOfSpace + 4, line.length());
- callerString = reshapeMethodName(callerString);
- calleeString = reshapeMethodName(calleeString);
- Node<String> callerNode = callHasNode.get(callerString);
- if (callerNode == null) {
- callerNode = new Node<>(callerString);
- callHasNode.put(callerString, callerNode);
- }
- Node<String> calleeNode = callHasNode.get(calleeString);
- if (calleeNode == null) {
- calleeNode = new Node<>(calleeString);
- callHasNode.put(calleeString, calleeNode);
- }
- callerNode.addLink(calleeNode);
- });
+ try (Stream<String> lines = Files.lines(Paths.get(path))) {
+ lines.forEach(line -> {
+ if (line.charAt(0) != 'M') {
+ return;
+ }
+ int indexOfSpace = line.indexOf(" ");
+ String callerString = line.substring(2, indexOfSpace);
+ String calleeString = line.substring(indexOfSpace + 4, line.length());
+ callerString = reshapeMethodName(callerString);
+ calleeString = reshapeMethodName(calleeString);
+ Node<String> callerNode = callHasNode.get(callerString);
+ if (callerNode == null) {
+ callerNode = new Node<>(callerString);
+ callHasNode.put(callerString, callerNode);
+ }
+ Node<String> calleeNode = callHasNode.get(calleeString);
+ if (calleeNode == null) {
+ calleeNode = new Node<>(calleeString);
+ callHasNode.put(calleeString, calleeNode);
+ }
+ callerNode.addLink(calleeNode);
+ });
+ }
return new Graph<>(callHasNode);
} catch (IOException ex) {
logger.log(Level.SEVERE, "Failed to open {0}", path);
@@ -63,23 +62,24 @@ public class CallGraphReader {
public static Map<String, Set<String>> parseFileToMap(String path) {
Map<String, Set<String>> nodeHasLinks = new HashMap<>();
try {
- Stream<String> lines = Files.lines(Paths.get(path));
- lines.forEach(line -> {
- if (line.charAt(0) != 'M') {
- return;
- }
- 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);
- });
+ try (Stream<String> lines = Files.lines(Paths.get(path))) {
+ lines.forEach(line -> {
+ if (line.charAt(0) != 'M') {
+ return;
+ }
+ 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.log(Level.SEVERE, null, ex);
}
@@ -91,11 +91,4 @@ public class CallGraphReader {
.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/memoizeit/graph/Graph.java b/src/main/java/br/ufrgs/inf/prosoft/memoizeit/graph/Graph.java
index 1d30440..17c6bc6 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
@@ -37,7 +37,7 @@ public class Graph<U> {
}
public Collection<Edge<U>> getEdges() {
- return this.contentHasNode.values().stream()
+ return getNodes().stream()
.map(node
-> node.getLinks().stream()
.map(link -> new Edge<>(node, link))
@@ -49,4 +49,9 @@ public class Graph<U> {
});
}
+ public Collection<Node<U>> getRoots() {
+ Collection<Node<U>> roots = new ArrayList<>(getNodes());
+ getEdges().forEach(edge -> roots.remove(edge.getTarget()));
+ return roots;
+ }
}
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 7390668..5494b56 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/memoizeit/MemoizeIt.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/memoizeit/MemoizeIt.java
@@ -13,6 +13,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.function.Consumer;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
@@ -23,10 +24,6 @@ import java.util.stream.Collectors;
*/
public class MemoizeIt {
- // Total program execution time
- private long totalProgramExecution;
- // Average of all occurrences execution time
- private double averageProgramExecution;
// Minimum Execution Time Threshold
private long minimumExecutionTime;
// Minimum Relative Execution Time Threshold
@@ -37,32 +34,18 @@ public class MemoizeIt {
private double minimumHitRatio;
// List of methods called
private List<Method> methods;
- // Stoping condition to iterative algorithm
- private boolean maxDepthReached;
// Call Graph
private Graph<String> callGraph;
private static final Logger logger = Logger.getLogger(MemoizeIt.class.getName());
public MemoizeIt() {
- this.maxDepthReached = false;
this.minimumHitRatio = 0.5;
this.minimumMethodCalls = 2;
this.minimumRelativeTime = 1.0;
this.minimumExecutionTime = 5;
}
- public MemoizeIt(long totalProgramExecution) {
- this();
- this.maxDepthReached = false;
- this.totalProgramExecution = totalProgramExecution;
- }
-
- public MemoizeIt setTotalProgramExecution(long totalProgramExecution) {
- this.totalProgramExecution = totalProgramExecution;
- return this;
- }
-
public MemoizeIt setMinimumExecutionTime(long minimumExecutionTime) {
this.minimumExecutionTime = minimumExecutionTime;
return this;
@@ -93,31 +76,69 @@ public class MemoizeIt {
return this;
}
- private void estimateTotalProgramExecution() {
- this.totalProgramExecution = this.methods.stream().map(Method::getTotalExecutionTime).reduce(Long::sum).get();
- }
-
- private void calculateAverageExecutionTime() {
- this.averageProgramExecution = this.methods.stream().map(Method::getAverageExecutionTime).reduce(Long::sum).get();
- this.averageProgramExecution /= this.methods.size();
+ private Method getMethodByName(String name) {
+ try {
+ return this.methods.stream()
+ .filter(method -> method.getName().equals(name))
+ .findAny().get();
+ } catch (Exception ex) {
+ return null;
+ }
}
// 3.1 time and frequency profiling
private void filterInitialCandidates() {
- logger.log(Level.INFO, "Fitering {0} initial candidates", this.methods.size());
- if (this.totalProgramExecution == 0) {
- logger.log(Level.WARNING, "Total program execution not informed. Using average of calls");
- calculateAverageExecutionTime();
- }
+ logger.log(Level.INFO, "Fitering {0} initial candidates by frequency and average execution time", this.methods.size());
int i = 0;
while (i < this.methods.size()) {
Method method = this.methods.get(i);
double totalExecutionTime = method.getTotalExecutionTime();
double averageExecutionTime = totalExecutionTime / method.getOccurrencesSize();
- double relativeExecutionTime = this.totalProgramExecution == 0 ? averageExecutionTime / this.averageProgramExecution : totalExecutionTime / this.totalProgramExecution;
- if (method.getOccurrencesSize() < this.minimumMethodCalls
- || averageExecutionTime < this.minimumExecutionTime
- || relativeExecutionTime < this.minimumRelativeTime) {
+ if (method.getOccurrencesSize() < this.minimumMethodCalls || averageExecutionTime < this.minimumExecutionTime) {
+ this.methods.remove(method);
+ continue;
+ }
+ i++;
+ }
+ logger.log(Level.INFO, "Calculating representativity of {0} methods", this.methods.size());
+ Collection<Node<String>> roots = this.callGraph.getRoots();
+ roots.stream().forEach(root -> {
+ Method method = getMethodByName(root.getContent());
+ if (method == null) {
+ return;
+ }
+ if (method.getRepresentativeness() != 0) {
+ return;
+ }
+ method.setRepresentativeness(1);
+ long rootAverageExecutionTime = method.getAverageExecutionTime();
+ root.getLinks().stream().forEach(new Consumer<Node<String>>() {
+
+ private final Collection<Node<String>> visited = new ArrayList<>();
+
+ @Override
+ public void accept(Node<String> node) {
+ if (visited.contains(node)) {
+ return;
+ }
+ visited.add(node);
+ Method callee = getMethodByName(node.getContent());
+ if (callee != null && callee.getRepresentativeness() == 0) {
+ callee.setRepresentativeness(callee.getAverageExecutionTime() / rootAverageExecutionTime);
+ }
+ node.getLinks().stream().forEach(this);
+ }
+ });
+
+ });
+ roots = null;
+ this.methods.stream().filter(method -> method.getRepresentativeness() == 0)
+ .forEach(method -> method.setRepresentativeness(1));
+ logger.log(Level.INFO, "Fitering {0} candidates by representativeness", this.methods.size());
+ i = 0;
+ while (i < this.methods.size()) {
+ Method method = this.methods.get(i);
+ if (method.getRepresentativeness() < this.minimumRelativeTime) {
this.methods.remove(method);
continue;
}
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 c522bba..1f9dba9 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/memoizeit/Method.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/memoizeit/Method.java
@@ -28,6 +28,7 @@ public class Method {
private final String name;
private final List<Occurrence> occurrences;
+ private double representativeness;
private Map<String, List<Occurrence>> groupByParameter;
private Boolean fullyExplored;
private final boolean isStatic;
@@ -47,6 +48,14 @@ public class Method {
return this.occurrences.size();
}
+ public void setRepresentativeness(double representativeness) {
+ this.representativeness = representativeness;
+ }
+
+ public double getRepresentativeness() {
+ return representativeness;
+ }
+
public int getDistinctOccurrencesSize() {
return this.groupByParameter.size();
}
@@ -83,8 +92,9 @@ public class Method {
System.out.println();
}
if (depth < Integer.MAX_VALUE) {
- Occurrence truncated = occurrence.getView(depth);
- Method.this.fullyExplored = truncated == occurrence;
+ OccurrenceConcrete thisOccurrence = occurrence.getConcrete();
+ OccurrenceConcrete truncated = thisOccurrence.getView(depth);
+ Method.this.fullyExplored = truncated == thisOccurrence;
occurrence = truncated;
}
String parameters = occurrence.getParameters().toString();
diff --git a/src/main/java/br/ufrgs/inf/prosoft/memoizeit/OccurrenceConcrete.java b/src/main/java/br/ufrgs/inf/prosoft/memoizeit/OccurrenceConcrete.java
index 8304e55..c21222d 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/memoizeit/OccurrenceConcrete.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/memoizeit/OccurrenceConcrete.java
@@ -77,6 +77,9 @@ public class OccurrenceConcrete extends Occurrence {
return this;
}
this.truncated = false;
+ if (depth > 512) {
+ return this;
+ }
Object returnValue = ObjectUtils.deepCopy(this.returnValue);
Action onTruncate = () -> {
this.truncated = true;
@@ -88,6 +91,9 @@ public class OccurrenceConcrete extends Occurrence {
ObjectUtils.truncateObject(parameterView, depth, onTruncate);
return new Parameter(parameter.getType(), parameterView);
}).collect(Collectors.toList());
+ if (!this.truncated) {
+ return this;
+ }
OccurrenceConcrete occurrenceConcrete = new OccurrenceConcrete(getInstance(), returnValue, parameters, getStartTime(), getEndTime());
return occurrenceConcrete;
}
diff --git a/src/main/java/br/ufrgs/inf/prosoft/memoizeit/OccurrenceReference.java b/src/main/java/br/ufrgs/inf/prosoft/memoizeit/OccurrenceReference.java
index 1c036aa..490d924 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/memoizeit/OccurrenceReference.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/memoizeit/OccurrenceReference.java
@@ -5,6 +5,7 @@
*/
package br.ufrgs.inf.prosoft.memoizeit;
+import br.ufrgs.inf.prosoft.trace.Return;
import br.ufrgs.inf.prosoft.trace.TraceConcrete;
import br.ufrgs.inf.prosoft.trace.reader.Traces;
import java.util.ArrayList;
@@ -30,11 +31,8 @@ public class OccurrenceReference extends Occurrence {
if (this.occurrenceConcrete != null) {
return this.occurrenceConcrete.getReturnValue();
}
- TraceConcrete traceConcrete = Traces.getTraceConcrete(this.index);
- if (traceConcrete != null && traceConcrete.getReturn() != null) {
- return traceConcrete.getReturn().getData();
- }
- return null;
+ Return returnValue = Traces.getTraceReturn(this.index);
+ return returnValue == null ? null : returnValue.getData();
}
@Override
@@ -42,13 +40,10 @@ public class OccurrenceReference extends Occurrence {
if (this.occurrenceConcrete != null) {
return this.occurrenceConcrete.getParameters();
}
- TraceConcrete traceConcrete = Traces.getTraceConcrete(this.index);
- if (traceConcrete != null && traceConcrete.getParameters() != null) {
- return traceConcrete.getParameters().stream()
- .map(parameter -> new Parameter(parameter.getType(), parameter.getData()))
- .collect(Collectors.toList());
- }
- return new ArrayList<>();
+ List<br.ufrgs.inf.prosoft.trace.Parameter> parameters = Traces.getTraceParameter(this.index);
+ return parameters.stream()
+ .map(parameter -> new Parameter(parameter.getType(), parameter.getData()))
+ .collect(Collectors.toList());
}
@Override