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;
+ }
+
}