memoizeit

added iterative approach

10/21/2018 3:59:16 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 08c288e..8c9ba22 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
@@ -49,17 +49,21 @@ public class TraceReader {
         Map<String, List<Occurrence>> methodNameHasOccurrences = new HashMap<>();
         while (!traces.isEmpty()) {
             Trace trace = traces.remove(0);
-            List<Object> parameters = new ArrayList<>();
-            trace.getParameters().forEach((parameter) -> {
-                parameters.add(parameter.getData());
-            });
-            Occurrence occurrence = new Occurrence(trace.getReturn().getData(), parameters, trace.getStartTime(), trace.getEndTime());
             try {
-                methodNameHasOccurrences.get(trace.getName()).add(occurrence);
-            } catch (Exception ex) {
-                List<Occurrence> occurrences = new ArrayList<>();
-                occurrences.add(occurrence);
-                methodNameHasOccurrences.put(trace.getName(), occurrences);
+                List<Object> parameters = new ArrayList<>();
+                trace.getParameters().forEach((parameter) -> {
+                    parameters.add(parameter.getData());
+                });
+                Occurrence occurrence = new Occurrence(trace.getReturn().getData(), parameters, trace.getStartTime(), trace.getEndTime());
+                try {
+                    methodNameHasOccurrences.get(trace.getName()).add(occurrence);
+                } catch (Exception ex) {
+                    List<Occurrence> occurrences = new ArrayList<>();
+                    occurrences.add(occurrence);
+                    methodNameHasOccurrences.put(trace.getName(), occurrences);
+                }
+            } catch (Exception e) {
+                System.err.println("Trace discarted: " + trace);
             }
         }
         List<Method> methods = new 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 6d154ee..59a0795 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/memoizeit/MemoizeIt.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/memoizeit/MemoizeIt.java
@@ -27,8 +27,11 @@ public class MemoizeIt {
     private double minimumHitRatio;
     // List of methods called
     private List<Method> methods;
+    // Stoping condition to iterative algorithm
+    private boolean maxDepthReached;
 
     public MemoizeIt() {
+        this.maxDepthReached = false;
         this.minimumHitRatio = 0.5;
         this.minimumMethodCalls = 2;
         this.minimumRelativeTime = 1.0;
@@ -37,6 +40,7 @@ public class MemoizeIt {
 
     public MemoizeIt(long totalProgramExecution) {
         this();
+        this.maxDepthReached = false;
         this.totalProgramExecution = totalProgramExecution;
     }
 
@@ -107,11 +111,25 @@ public class MemoizeIt {
 
 //    3.2 input-output profiling
     private void refineCandidates() {
+        refineCandidates(Integer.MAX_VALUE);
+    }
+
+    private void refineCandidates(int depth) {
         int i = 0;
         while (i < this.methods.size()) {
             Method method = this.methods.get(i);
             int occurrencesSize = method.getOccurrencesSize();
-            method.groupByParameter();
+            if (depth < Integer.MAX_VALUE) {
+                method.groupByParameter(depth);
+                if (method.wasFullyExplored()) {
+                    this.maxDepthReached = true;
+                    i++;
+                    continue;
+                }
+                this.maxDepthReached = false;
+            } else {
+                method.groupByParameter();
+            }
             int distinctOccurrencesSize = method.getDistinctOccurrencesSize();
             if (occurrencesSize == distinctOccurrencesSize) {
                 this.methods.remove(i);
@@ -130,6 +148,23 @@ public class MemoizeIt {
         }
     }
 
+    private void refineCandidatesIteratively() {
+        int depth = 1;
+        while (true) {
+            System.out.println("Exploring depth " + depth);
+            refineCandidates(depth);
+            if (this.methods.isEmpty()) {
+                System.out.println("No caching candidates left to explore");
+                break;
+            }
+            if (this.maxDepthReached) {
+                System.out.println("Max depth reached");
+                break;
+            }
+            depth *= 2;
+        }
+    }
+
     public void removeChangefulMethods() {
         if (this.methods.isEmpty()) {
             throw new RuntimeException("Empty execution traces");
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 edbbbe2..01a62eb 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/memoizeit/Method.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/memoizeit/Method.java
@@ -20,20 +20,22 @@ public class Method {
     private final String name;
     private final List<Occurrence> occurrences;
     private Map<String, List<Occurrence>> groupByParameter;
+    private Boolean fullyExplored;
 
     public Method(String name, List<Occurrence> occurrences) {
         this.name = name;
         this.occurrences = occurrences;
+        this.fullyExplored = false;
     }
 
     public int getOccurrencesSize() {
         return this.occurrences.size();
     }
-    
+
     public int getDistinctOccurrencesSize() {
         return this.groupByParameter.size();
     }
-    
+
     public long getTotalExecutionTime() {
         long averageExecutionTime = 0;
         for (Occurrence occurrence : this.occurrences) {
@@ -46,6 +48,27 @@ public class Method {
         return getTotalExecutionTime() / this.occurrences.size();
     }
 
+    protected boolean wasFullyExplored() {
+        return this.fullyExplored;
+    }
+
+    protected void groupByParameter(int depth) {
+        this.groupByParameter = new HashMap<>();
+        this.occurrences.forEach((occurrence) -> {
+            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);
+            }
+        });
+    }
+
     protected void groupByParameter() {
         this.groupByParameter = new HashMap<>();
         while (!this.occurrences.isEmpty()) {
diff --git a/src/main/java/br/ufrgs/inf/prosoft/memoizeit/ObjectUtils.java b/src/main/java/br/ufrgs/inf/prosoft/memoizeit/ObjectUtils.java
new file mode 100644
index 0000000..bc4c67e
--- /dev/null
+++ b/src/main/java/br/ufrgs/inf/prosoft/memoizeit/ObjectUtils.java
@@ -0,0 +1,63 @@
+/*
+ * 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;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ *
+ * @author romulo
+ */
+public class ObjectUtils {
+
+    public static Object truncateObject(Object object, int depth) {
+        if (depth == 0) {
+            object = "...";
+        }
+        if (object instanceof Map) {
+            Map<String, Object> map = (Map<String, Object>) object;
+            map.entrySet().forEach((entry) -> {
+                truncateObject(entry.getValue(), depth - 1);
+            });
+        } else if (object instanceof Collection) {
+            Collection collection = (Collection) object;
+            collection.forEach((item) -> {
+                truncateObject(item, depth - 1);
+            });
+        }
+        return object;
+    }
+
+    public static List<Object> deepCopy(List<Object> object) {
+        List<Object> collection = new ArrayList<>();
+        object.forEach((item) -> {
+            collection.add(deepCopy(item));
+        });
+        return collection;
+    }
+
+    public static Object deepCopy(Object object) {
+        try {
+            try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream)) {
+                objectOutputStream.writeObject(object);
+                try (ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray()); ObjectInputStream objectInputStream = new ObjectInputStream(inputStream)) {
+                    return objectInputStream.readObject();
+                }
+            }
+        } catch (IOException | ClassNotFoundException ex) {
+            System.err.println("[MemoizeIt] clone exception: " + ex);
+            return null;
+        }
+    }
+}
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 038b7d9..c851120 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/memoizeit/Occurrence.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/memoizeit/Occurrence.java
@@ -6,6 +6,7 @@
 package br.ufrgs.inf.prosoft.memoizeit;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  *
@@ -17,12 +18,14 @@ public class Occurrence {
     private final List<Object> parameters;
     private final long startTime;
     private final long endTime;
+    private boolean truncated;
 
     public Occurrence(Object returnValue, List<Object> parameters, long startTime, long endTime) {
         this.returnValue = returnValue;
         this.parameters = parameters;
         this.startTime = startTime;
         this.endTime = endTime;
+        this.truncated = true;
     }
 
     public Object getReturnValue() {
@@ -37,4 +40,37 @@ public class Occurrence {
         return this.endTime - this.startTime;
     }
 
+    private Object truncateObject(Object object, int depth) {
+        if (depth == 0) {
+            object = "...";
+            this.truncated = true;
+            return object;
+        }
+        if (object instanceof Map) {
+            Map<String, Object> map = (Map<String, Object>) object;
+            map.entrySet().forEach((entry) -> {
+                entry.setValue(truncateObject(entry.getValue(), depth - 1));
+            });
+        } else if (object instanceof List) {
+            List list = (List) object;
+            for (int i = 0; i < list.size(); i++) {
+                list.set(i, truncateObject(list.get(i), depth - 1));
+            }
+        }
+        return object;
+    }
+
+    protected Occurrence getView(int depth) {
+        if (!this.truncated) {
+            return this;
+        }
+        this.truncated = false;
+        Object returnValue = ObjectUtils.deepCopy(this.returnValue);
+        truncateObject(returnValue, depth);
+        List<Object> parameters = ObjectUtils.deepCopy(this.parameters);
+        truncateObject(parameters, depth);
+        Occurrence occurrence = new Occurrence(returnValue, parameters, startTime, endTime);
+        return occurrence;
+    }
+
 }