memoizeit

close streams, use traceparameter and tracereturn, added

12/6/2018 3:49:31 AM

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