memoizeit

parallel streams. synchronized. and refine each candidate

12/5/2018 10:34:35 AM

Details

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 7567c82..3dfd896 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
@@ -26,7 +26,7 @@ import java.util.stream.Collectors;
  *
  * @author romulo
  */
-public class TraceReader extends br.ufrgs.inf.prosoft.trace.TraceReader {
+public class TraceReader extends br.ufrgs.inf.prosoft.trace.reader.TraceReader {
 
     private static final Logger logger = Logger.getLogger(TraceReader.class.getName());
 
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 43e5f54..7390668 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/memoizeit/MemoizeIt.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/memoizeit/MemoizeIt.java
@@ -131,38 +131,24 @@ public class MemoizeIt {
     }
 
 //    3.2 input-output profiling
-    private void refineCandidatesExhaustively() {
-        logger.log(Level.INFO, "Exhaustively refining {0} candidates", this.methods.size());
-        refineCandidates(Integer.MAX_VALUE);
+    private void refineCandidates() {
+        refineCandidates(true);
     }
 
-    private void refineCandidates(int depth) {
+    private void refineCandidates(boolean iteratively) {
+        logger.log(Level.INFO, "Refining {0} candidates", this.methods.size());
         int i = 0;
+        this.methods.sort((m1, m2) -> Integer.compare(m1.getOccurrencesSize(), m2.getOccurrencesSize()));
         while (i < this.methods.size()) {
             Method method = this.methods.get(i);
-            int occurrencesSize = method.getOccurrencesSize();
-            if (depth < Integer.MAX_VALUE) {
-                method.groupByParameter(depth);
-                if (method.wasFullyExplored()) {
-                    this.maxDepthReached = true;
-                    i++;
-                    continue;
-                }
-                this.maxDepthReached = false;
+            method.removeUnusedFields(this.callGraph.getNode(method.getName()));
+            boolean refineCandidate;
+            if (iteratively) {
+                refineCandidate = refineCandidateIteratively(method);
             } else {
-                method.groupByParameter();
+                refineCandidate = refineCandidateExhaustively(method);
             }
-            int distinctOccurrencesSize = method.getDistinctOccurrencesSize();
-            if (occurrencesSize == distinctOccurrencesSize) {
-                this.methods.remove(i);
-                continue;
-            }
-            if (method.isChangeful()) {
-                this.methods.remove(i);
-                continue;
-            }
-            double potentialHitRatio = method.getPotentialHitRatio();
-            if (potentialHitRatio < this.minimumHitRatio) {
+            if (refineCandidate) {
                 this.methods.remove(i);
                 continue;
             }
@@ -170,22 +156,36 @@ public class MemoizeIt {
         }
     }
 
-    private void refineCandidatesIteratively() {
-        logger.log(Level.INFO, "Iteratively refining {0} candidates", this.methods.size());
+    private boolean refineCandidateExhaustively(Method method) {
+        return refineCandidate(method, Integer.MAX_VALUE);
+    }
+
+    private boolean refineCandidateIteratively(Method method) {
+        logger.log(Level.INFO, "Iteratively refining {0}", method);
         int depth = 1;
-        while (true) {
+        while (!method.wasFullyExplored()) {
             logger.log(Level.INFO, "Exploring depth {0}", depth);
-            refineCandidates(depth);
-            if (this.methods.isEmpty()) {
-                logger.log(Level.INFO, "No caching candidates left to explore");
-                break;
-            }
-            if (this.maxDepthReached) {
-                logger.log(Level.INFO, "Max depth reached");
-                break;
+            boolean refineCandidate = refineCandidate(method, depth);
+            if (refineCandidate) {
+                logger.log(Level.INFO, "Removing candidate");
+                return true;
             }
             depth *= 2;
         }
+        return false;
+    }
+
+    private boolean refineCandidate(Method method, int depth) {
+        int occurrencesSize = method.getOccurrencesSize();
+        method.groupByParameter(depth);
+        int distinctOccurrencesSize = method.getDistinctOccurrencesSize();
+        if (occurrencesSize == distinctOccurrencesSize) {
+            return true;
+        }
+        if (method.isChangeful()) {
+            return true;
+        }
+        return method.getPotentialHitRatio() < this.minimumHitRatio;
     }
 
     private Collection<Method> getIndirectCallees(List<Node<String>> visited, String rootPackage, Node<String> node) {
@@ -329,7 +329,7 @@ public class MemoizeIt {
         }
         filterInitialCandidates();
         removeUnusedFields();
-        refineCandidatesIteratively();
+        refineCandidates(true);
     }
 
     public void suggestCachingImplementations() {
@@ -351,8 +351,7 @@ public class MemoizeIt {
             throw new RuntimeException("Call Graph not set");
         }
         filterInitialCandidates();
-        removeUnusedFields();
-        refineCandidatesIteratively();
+        refineCandidates();
         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 489727f..c522bba 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/memoizeit/Method.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/memoizeit/Method.java
@@ -15,7 +15,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.function.Consumer;
-import java.util.function.Function;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -71,20 +70,33 @@ public class Method {
     }
 
     protected void groupByParameter(int depth) {
+        logger.log(Level.INFO, "Grouping by parameters {0} occurrences of {1}", new Object[]{this.name, this.occurrences.size()});
         this.groupByParameter = new HashMap<>();
-        this.occurrences.forEach(occurrence -> {
-            if (depth < Integer.MAX_VALUE) {
-                Occurrence truncated = occurrence.getView(depth);
-                this.fullyExplored = truncated == occurrence;
-                occurrence = truncated;
-            }
-            String parameters = occurrence.getParameters().toString();
-            try {
-                this.groupByParameter.get(parameters).add(occurrence);
-            } catch (Exception e) {
-                List<Occurrence> occurrences = new ArrayList<>();
-                occurrences.add(occurrence);
-                this.groupByParameter.put(parameters, occurrences);
+        this.occurrences.stream().parallel().forEach(new Consumer<Occurrence>() {
+            int i = 0;
+
+            @Override
+            public void accept(Occurrence occurrence) {
+                System.out.print(".");
+                System.out.flush();
+                if (++i % 100 == 0) {
+                    System.out.println();
+                }
+                if (depth < Integer.MAX_VALUE) {
+                    Occurrence truncated = occurrence.getView(depth);
+                    Method.this.fullyExplored = truncated == occurrence;
+                    occurrence = truncated;
+                }
+                String parameters = occurrence.getParameters().toString();
+                synchronized (Method.this.groupByParameter) {
+                    try {
+                        Method.this.groupByParameter.get(parameters).add(occurrence);
+                    } catch (Exception e) {
+                        List<Occurrence> occurrences = new ArrayList<>();
+                        occurrences.add(occurrence);
+                        Method.this.groupByParameter.put(parameters, occurrences);
+                    }
+                }
             }
         });
     }
@@ -99,7 +111,9 @@ public class Method {
                 continue;
             }
             Occurrence firstOccurrence = entry.getValue().get(0);
-            if (entry.getValue().stream().anyMatch(occurrence -> occurrence.getReturnValue() != null && !occurrence.getReturnValue().equals(firstOccurrence.getReturnValue()))) {
+            if (entry.getValue().stream()
+                    .anyMatch(occurrence -> occurrence.getReturnValue() != null
+                    && !occurrence.getReturnValue().equals(firstOccurrence.getReturnValue()))) {
                 return true;
             }
         }
@@ -113,7 +127,7 @@ public class Method {
     }
 
     protected void removeUnusedFields(Node<String> methodNode) {
-        logger.log(Level.INFO, "Analysing fields of {0} occurrences of {1}", new Object[]{this.occurrences.size(), this.name});
+        logger.log(Level.INFO, "Removing unused fields of {0} occurrences of {1}", new Object[]{this.occurrences.size(), this.name});
         if (methodNode == null) {
             logger.log(Level.WARNING, "methodNode null: {0}", this.name);
             return;
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 2bad9a6..8304e55 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/memoizeit/OccurrenceConcrete.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/memoizeit/OccurrenceConcrete.java
@@ -8,11 +8,11 @@ package br.ufrgs.inf.prosoft.memoizeit;
 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;
+import java.util.stream.Collectors;
 
 /**
  *
@@ -55,7 +55,7 @@ public class OccurrenceConcrete extends Occurrence {
 
     @Override
     protected Occurrence removeUnusedFields(Node<String> methodNode) {
-        for (Parameter parameter : getParameters()) {
+        getParameters().stream().parallel().forEach((parameter) -> {
             String parameterType = parameter.getType();
             if (parameter.getData() instanceof Collection) {
                 Collection collection = (Collection) parameter.getData();
@@ -67,7 +67,7 @@ public class OccurrenceConcrete extends Occurrence {
                 Map<String, Object> map = (Map<String, Object>) parameter.getData();
                 removeUnusedFields(map, parameterType, methodNode);
             }
-        }
+        });
         return this;
     }
 
@@ -82,12 +82,12 @@ public class OccurrenceConcrete extends Occurrence {
             this.truncated = true;
         };
         ObjectUtils.truncateObject(returnValue, 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));
-        }
+        List<Parameter> parameters = this.parameters.stream()
+                .map(parameter -> {
+                    Object parameterView = ObjectUtils.deepCopy(parameter.getData());
+                    ObjectUtils.truncateObject(parameterView, depth, onTruncate);
+                    return new Parameter(parameter.getType(), parameterView);
+                }).collect(Collectors.toList());
         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 d5cbc8f..1c036aa 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/memoizeit/OccurrenceReference.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/memoizeit/OccurrenceReference.java
@@ -6,7 +6,7 @@
 package br.ufrgs.inf.prosoft.memoizeit;
 
 import br.ufrgs.inf.prosoft.trace.TraceConcrete;
-import br.ufrgs.inf.prosoft.trace.Traces;
+import br.ufrgs.inf.prosoft.trace.reader.Traces;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.stream.Collectors;