Details
diff --git a/src/main/java/br/ufrgs/inf/prosoft/tfcache/configuration/Configuration.java b/src/main/java/br/ufrgs/inf/prosoft/tfcache/configuration/Configuration.java
new file mode 100644
index 0000000..10ddb8c
--- /dev/null
+++ b/src/main/java/br/ufrgs/inf/prosoft/tfcache/configuration/Configuration.java
@@ -0,0 +1,95 @@
+package br.ufrgs.inf.prosoft.tfcache.configuration;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ *
+ * @author root
+ */
+public class Configuration {
+
+ private static final Logger LOGGER = Logger.getLogger(Configuration.class.getName());
+
+ private static String level = "method";
+ private static String output = null;
+ private static String changeability = "allow";
+ private static String staleness = "ignore";
+ private static String kernel = "exhaustive";
+
+ public static void setLevel(String level) {
+ if (level == null) {
+ LOGGER.log(Level.INFO, "Using default level: {0}", Configuration.level);
+ return;
+ }
+ if (!level.equals("method") && !level.equals("input")) {
+ LOGGER.log(Level.SEVERE, "Unrecognised option for level");
+ System.exit(1);
+ }
+ Configuration.level = level;
+ }
+
+ public static String getLevel() {
+ return level;
+ }
+
+ public static void setOutput(String output) {
+ if (output == null || output.isBlank()) {
+ return;
+ }
+ Configuration.output = output;
+ }
+
+ public static String getOutput() {
+ return output;
+ }
+
+ public static void setChangeability(String changeability) {
+ if (changeability == null) {
+ LOGGER.log(Level.INFO, "Using default changeability: {0}", Configuration.changeability);
+ return;
+ }
+ if (!changeability.equals("allow") && !changeability.equals("deny")) {
+ LOGGER.log(Level.SEVERE, "Unrecognised option for changeability");
+ System.exit(1);
+ }
+ Configuration.changeability = changeability;
+ }
+
+ public static String getChangeability() {
+ return changeability;
+ }
+
+ public static void setStaleness(String staleness) {
+ if (staleness == null) {
+ LOGGER.log(Level.INFO, "Using default staleness: {0}", Configuration.staleness);
+ return;
+ }
+ if (!staleness.equals("ignore") && !staleness.equals("shrink")) {
+ LOGGER.log(Level.SEVERE, "Unrecognised option for staleness");
+ System.exit(1);
+ }
+ Configuration.staleness = staleness;
+ }
+
+ public static String getStaleness() {
+ return staleness;
+ }
+
+ public static void setKernel(String kernel) {
+ if (kernel == null) {
+ LOGGER.log(Level.INFO, "Using default kernel: {0}", Configuration.kernel);
+ return;
+ }
+ if (!kernel.equals("exhaustive") && !kernel.equals("optimised")) {
+ LOGGER.log(Level.SEVERE, "Unrecognised option for kernel");
+ System.exit(1);
+ }
+ Configuration.kernel = kernel;
+ }
+
+ public static String getKernel() {
+ return kernel;
+ }
+
+}
diff --git a/src/main/java/br/ufrgs/inf/prosoft/tfcache/Main.java b/src/main/java/br/ufrgs/inf/prosoft/tfcache/Main.java
index e33362d..f7ac970 100755
--- a/src/main/java/br/ufrgs/inf/prosoft/tfcache/Main.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/tfcache/Main.java
@@ -6,6 +6,7 @@
package br.ufrgs.inf.prosoft.tfcache;
import br.ufrgs.inf.prosoft.tfcache.adapter.TraceReader;
+import br.ufrgs.inf.prosoft.tfcache.configuration.Configuration;
import br.ufrgs.inf.prosoft.tfcache.metadata.Method;
import br.ufrgs.inf.prosoft.trace.Trace;
import java.util.List;
@@ -27,9 +28,7 @@ public class Main {
System.setProperty("java.util.logging.SimpleFormatter.format", "[%1$tF %1$tT+%1$tL] [%4$-7s] [TFCache] %5$s %n");
if (args.length < 1) {
- System.err.println("--trace=<TracePath>");
- System.err.println("--trace=<TracePath> --level=<method|input> [--output=<outputPath>] [--changeability=<true|false>]");
- System.err.println("--trace=<TracePath> --level=input --output=<outputPath>");
+ System.err.println("--trace=<TracePath> [--level=<method|input>] [--output=<outputPath>] [--changeability=<allow|deny>] [--staleness=<ignore|shrink>] [--kernel=<exhaustive|optimised>]");
System.exit(1);
}
@@ -47,35 +46,26 @@ public class Main {
}));
String tracePath = arguments.get("trace");
- if (tracePath == null) {
+ if (tracePath == null || tracePath.isBlank()) {
System.err.println("<TracePath> is required");
System.exit(1);
}
- String level = arguments.get("level");
- if (level == null) {
- level = "method";
- LOGGER.log(Level.INFO, "Using default level: {0}", level);
- }
- String changeability = arguments.get("changeability");
- if (changeability == null) {
- changeability = "false";
- LOGGER.log(Level.INFO, "Using default changeability: {0}", changeability);
- }
- String output = arguments.get("output");
- if (level.equals("input") && output == null) {
- System.err.println("outputPath is required for input-level recommendations");
+
+ Configuration.setLevel(arguments.get("level"));
+ Configuration.setOutput(arguments.get("output"));
+ if (Configuration.getLevel().equals("input") && Configuration.getOutput() == null) {
+ LOGGER.log(Level.SEVERE, "Output is required for input-level recommendations");
System.exit(1);
}
+ Configuration.setChangeability(arguments.get("changeability"));
+ Configuration.setStaleness(arguments.get("staleness"));
+ Configuration.setKernel(arguments.get("kernel"));
LOGGER.log(Level.INFO, "Reading traces");
List<Trace> traces = TraceReader.parseFile(tracePath);
LOGGER.log(Level.INFO, "Grouping {0} traces by methods", traces.size());
List<Method> methods = TraceReader.groupByMethods(traces);
TFCache tfCache = new TFCache(methods);
- if (level.equals("input")) {
- tfCache.recommend(changeability.equals("true"), output);
- } else {
- tfCache.recommend(changeability.equals("true"));
- };
+ tfCache.recommend();
}
}
diff --git a/src/main/java/br/ufrgs/inf/prosoft/tfcache/metadata/GroupOfOccurrences.java b/src/main/java/br/ufrgs/inf/prosoft/tfcache/metadata/GroupOfOccurrences.java
index dfb2750..25ba662 100755
--- a/src/main/java/br/ufrgs/inf/prosoft/tfcache/metadata/GroupOfOccurrences.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/tfcache/metadata/GroupOfOccurrences.java
@@ -8,17 +8,11 @@ package br.ufrgs.inf.prosoft.tfcache.metadata;
import br.ufrgs.inf.prosoft.tfcache.Metrics;
import br.ufrgs.inf.prosoft.tfcache.Simulator;
import java.math.BigDecimal;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.logging.Level;
import java.util.logging.Logger;
-import java.util.stream.Collectors;
-import java.util.stream.LongStream;
import java.util.stream.Stream;
/**
@@ -54,16 +48,24 @@ public class GroupOfOccurrences {
return this.bestMetrics;
}
- public Long getTtl() {
+ public long getTtl() {
return getBestMetrics().getTtl();
}
- public Long getSavedTime() {
+ public long getHits() {
+ return getBestMetrics().getHits();
+ }
+
+ public long getStales() {
+ return getBestMetrics().getStales();
+ }
+
+ public long getSavedTime() {
return getBestMetrics().getSavedTime();
}
- public BigDecimal getHitsPerTimeInCache() {
- return getBestMetrics().getHitsPerTimeInCache();
+ public BigDecimal getSavedTimePerTimeInCache() {
+ return getBestMetrics().getSavedTimePerTimeInCache();
}
public Stream<Occurrence> occurrences() {
@@ -89,23 +91,9 @@ public class GroupOfOccurrences {
if (this.occurrences.size() < 2) {
throw new RuntimeException("Not reusable input");
}
+ this.occurrences.sort((occurrence1, occurrence2) -> Long.compare(occurrence1.getStartTime(), occurrence2.getStartTime()));
this.bestMetrics = new Metrics();
-
- Collection<Long> ttlsOfInterest = new HashSet<>();
- for (int hits = 1; hits < this.occurrences.size(); hits++) {
- for (int shift = 0; shift < this.occurrences.size() - hits; shift++) {
- long ttl = 0;
- for (int k = shift + 1; k < shift + 1 + hits; k++) {
- ttl += this.occurrences.get(k).getStartTime() - this.occurrences.get(k - 1).getEndTime();
- }
- if (ttl > 0) {
- ttlsOfInterest.add(ttl);
- }
- }
- }
- ttlsOfInterest.stream().parallel().forEach(actualTTL -> {
- Simulator.simulate(occurrences(), actualTTL, this.bestMetrics);
- });
+ Simulator.simulate(this.occurrences, this.bestMetrics);
}
}
diff --git a/src/main/java/br/ufrgs/inf/prosoft/tfcache/metadata/Method.java b/src/main/java/br/ufrgs/inf/prosoft/tfcache/metadata/Method.java
index bdfc484..29d3783 100755
--- a/src/main/java/br/ufrgs/inf/prosoft/tfcache/metadata/Method.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/tfcache/metadata/Method.java
@@ -9,9 +9,7 @@ import br.ufrgs.inf.prosoft.tfcache.Metrics;
import br.ufrgs.inf.prosoft.tfcache.Simulator;
import java.math.BigDecimal;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -68,8 +66,8 @@ public class Method {
return getBestMetrics().getSavedTime();
}
- public BigDecimal getHitsPerTimeInCache() {
- return getBestMetrics().getHitsPerTimeInCache();
+ public BigDecimal getSavedTimePerTimeInCache() {
+ return getBestMetrics().getSavedTimePerTimeInCache();
}
public Stream<Occurrence> occurrences() {
@@ -115,7 +113,6 @@ public class Method {
this.groupsOfOccurrences = inputHasOccurrences.entrySet().stream()
.map(entry -> new GroupOfOccurrences(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
- this.occurrences = null;
}
public void removeChangeableInputs() {
@@ -172,7 +169,6 @@ public class Method {
.map(Occurrence::getParametersSerialised)
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
return inputHasFrequency.values().stream().anyMatch(frequency -> frequency > 1);
-
}
public boolean isNotReusable() {
@@ -190,22 +186,8 @@ public class Method {
if (this.occurrences.size() < 2) {
return;
}
-
- Collection<Long> ttlsOfInterest = new HashSet<>();
- for (int hits = 1; hits < this.occurrences.size(); hits++) {
- for (int shift = 0; shift < this.occurrences.size() - hits; shift++) {
- long ttl = 0;
- for (int k = shift + 1; k < shift + 1 + hits; k++) {
- ttl += this.occurrences.get(k).getStartTime() - this.occurrences.get(k - 1).getEndTime();
- }
- if (ttl > 0) {
- ttlsOfInterest.add(ttl);
- }
- }
- }
- ttlsOfInterest.stream().parallel().forEach(actualTTL -> {
- Simulator.simulate(occurrences(), actualTTL, this.bestMetrics);
- });
+ this.occurrences.sort((occurrence1, occurrence2) -> Long.compare(occurrence1.getStartTime(), occurrence2.getStartTime()));
+ Simulator.simulate(this.occurrences, this.bestMetrics);
}
public void recommendTTLPerInput() {
@@ -213,13 +195,27 @@ public class Method {
groupByInput();
removeSingleOccurrences();
}
- groupsOfOccurrences().forEach(GroupOfOccurrences::calculateHitsPerTimeInCache);
+ groupsOfOccurrences().parallel().forEach(GroupOfOccurrences::calculateHitsPerTimeInCache);
if (this.bestMetrics == null) {
long savedTime = groupsOfOccurrences().map(GroupOfOccurrences::getSavedTime).reduce(Long::sum).get();
+ long hits = groupsOfOccurrences().map(GroupOfOccurrences::getHits).reduce(Long::sum).get();
+ long stales = groupsOfOccurrences().map(GroupOfOccurrences::getStales).reduce(Long::sum).get();
GroupOfOccurrences max = groupsOfOccurrences().max((group1, group2) -> Long.compare(group1.getSavedTime(), group2.getSavedTime())).get();
long ttl = max.getTtl();
- BigDecimal hitsPerTimeInCache = max.getHitsPerTimeInCache();
- this.bestMetrics = new Metrics(ttl, savedTime, hitsPerTimeInCache);
+ BigDecimal hitsPerTimeInCache = max.getSavedTimePerTimeInCache();
+ this.bestMetrics = new Metrics(ttl, hits, stales, savedTime, hitsPerTimeInCache);
+ }
+ }
+
+ public void removeNotRecommededInputs() {
+ if (this.groupsOfOccurrences == null || this.bestMetrics == null) {
+ throw new RuntimeException("Recommendations not called");
+ }
+ int initialCountofOccurrences = this.groupsOfOccurrences.size();
+ this.groupsOfOccurrences.removeIf(groupOfOccurrences -> groupOfOccurrences.getSavedTime() == 0);
+ int removedOccurrences = initialCountofOccurrences - this.groupsOfOccurrences.size();
+ if (removedOccurrences > 0) {
+ LOGGER.log(Level.INFO, "\tRemoved {0} of {1} inputs from method {2}", new Object[]{removedOccurrences, initialCountofOccurrences, this.name});
}
}
diff --git a/src/main/java/br/ufrgs/inf/prosoft/tfcache/Metrics.java b/src/main/java/br/ufrgs/inf/prosoft/tfcache/Metrics.java
index 196d3bd..4f34d9f 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/tfcache/Metrics.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/tfcache/Metrics.java
@@ -21,61 +21,73 @@ import java.util.stream.Stream;
public class Metrics implements Comparable<Metrics> {
private long ttl;
+ private long hits;
+ private long stales;
private long savedTime;
- private BigDecimal hitsPerTimeInCache;
+ private BigDecimal savedTimePerTimeInCache;
public Metrics() {
- this.hitsPerTimeInCache = new BigDecimal(BigInteger.ZERO);
+ this.savedTimePerTimeInCache = new BigDecimal(BigInteger.ZERO);
}
- public Metrics(long ttl, long savedTime, BigDecimal hitsPerTimeInCache) {
+ public Metrics(long ttl, long hits, long stales, long savedTime, BigDecimal hitsPerTimeInCache) {
this.ttl = ttl;
+ this.hits = hits;
+ this.stales = stales;
this.savedTime = savedTime;
- this.hitsPerTimeInCache = hitsPerTimeInCache;
+ this.savedTimePerTimeInCache = hitsPerTimeInCache;
}
public long getTtl() {
return this.ttl;
}
+ public long getHits() {
+ return this.hits;
+ }
+
+ public long getStales() {
+ return this.stales;
+ }
+
public long getSavedTime() {
return this.savedTime;
}
- public BigDecimal getHitsPerTimeInCache() {
- return this.hitsPerTimeInCache;
+ public BigDecimal getSavedTimePerTimeInCache() {
+ return this.savedTimePerTimeInCache;
}
- public synchronized void keepBestMetrics(long ttl, long hits, long timeInCache, long savedTime) {
- if (ttl < 0 || hits < 0 || timeInCache < 0 || savedTime < 0) {
- throw new RuntimeException("Metrics cannot be under zero. TTL: " + ttl + " hits: " + hits + " timeInCache: " + timeInCache + " savedTime: " + savedTime);
+ public synchronized void keepBestMetrics(long ttl, long hits, long timeInCache, long stales, long savedTime) {
+ if (ttl < 0 || hits < 0 || timeInCache < 0 || stales < 0 || savedTime < 0) {
+ throw new RuntimeException("Metrics cannot be under zero. TTL: " + ttl
+ + " hits: " + hits
+ + " timeInCache: " + timeInCache
+ + " stales: " + stales
+ + " savedTime: " + savedTime);
}
- if (ttl == 0 || hits == 0) {
+ if (ttl == 0 || hits == 0 || savedTime == 0) {
return;
}
- if (timeInCache == 0 || savedTime == 0) {
- throw new RuntimeException("timeInCache and savedTime should not be zero");
+ if (timeInCache == 0) {
+ throw new RuntimeException("timeInCache should not be zero");
}
- BigDecimal hitsPerTimeInCache = new BigDecimal(hits).divide(new BigDecimal(timeInCache), MathContext.DECIMAL128);
- if (this.ttl == 0
- || this.hitsPerTimeInCache.compareTo(hitsPerTimeInCache) == -1
- || (this.hitsPerTimeInCache == hitsPerTimeInCache && this.savedTime < savedTime)
- || (this.hitsPerTimeInCache == hitsPerTimeInCache && this.savedTime == savedTime && this.ttl > ttl)) {
+ BigDecimal savedTimePerTimeInCache = new BigDecimal(savedTime).divide(new BigDecimal(timeInCache), MathContext.DECIMAL128);
+ if (this.ttl == 0 || compareTo(ttl, hits, stales, savedTime, savedTimePerTimeInCache) == -1) {
this.ttl = ttl;
+ this.hits = hits;
+ this.stales = stales;
this.savedTime = savedTime;
- this.hitsPerTimeInCache = hitsPerTimeInCache;
+ this.savedTimePerTimeInCache = savedTimePerTimeInCache;
}
}
- public static void removeDominatedMetrics(Collection<Metrics> metrics) {
- Map<Long, List<Metrics>> groupBySavedTime = metrics.stream().collect(Collectors.groupingBy(Metrics::getSavedTime));
+ public static void removeDominatedMetrics(Collection<Metrics> allMetrics) {
+ Map<Long, List<Metrics>> groupBySavedTime = allMetrics.stream().collect(Collectors.groupingBy(Metrics::getSavedTime));
+ groupBySavedTime.remove(0L);
groupBySavedTime.forEach((savedTime, value) -> {
- if (savedTime == 0) {
- value.clear();
- return;
- }
Metrics max = value.stream().max(Metrics::compareTo).get();
- value.removeIf(metric -> metric.getHitsPerTimeInCache().compareTo(max.getHitsPerTimeInCache()) == -1);
+ value.removeIf(metric -> metric.getSavedTimePerTimeInCache().compareTo(max.getSavedTimePerTimeInCache()) == -1);
});
List<Metrics> localMaxima = groupBySavedTime.entrySet().stream()
@@ -84,27 +96,43 @@ public class Metrics implements Comparable<Metrics> {
.orElse(Stream.empty())
.collect(Collectors.toList());
- metrics.removeIf(metric -> !localMaxima.contains(metric));
+ allMetrics.removeIf(metrics -> !localMaxima.contains(metrics));
}
@Override
public int compareTo(Metrics other) {
- if (this.hitsPerTimeInCache.compareTo(other.hitsPerTimeInCache) == 1) {
+ return compareTo(other.ttl, other.hits, other.stales, other.savedTime, other.savedTimePerTimeInCache);
+ }
+
+ private int compareTo(long ttl, long hits, long stales, long savedTime, BigDecimal savedTimePerTimeInCache) {
+ if (this.savedTimePerTimeInCache.compareTo(savedTimePerTimeInCache) == 1) {
return 1;
}
- if (this.hitsPerTimeInCache.compareTo(other.hitsPerTimeInCache) == -1) {
+ if (this.savedTimePerTimeInCache.compareTo(savedTimePerTimeInCache) == -1) {
return -1;
}
- if (this.savedTime > other.savedTime) {
+ if (this.stales < stales) {
return 1;
}
- if (this.savedTime < other.savedTime) {
+ if (this.stales > stales) {
return -1;
}
- if (this.ttl < other.ttl) {
+ if (this.savedTime > savedTime) {
return 1;
}
- if (this.ttl > other.ttl) {
+ if (this.savedTime < savedTime) {
+ return -1;
+ }
+ if (this.hits > hits) {
+ return 1;
+ }
+ if (this.hits < hits) {
+ return -1;
+ }
+ if (this.ttl < ttl) {
+ return 1;
+ }
+ if (this.ttl > ttl) {
return -1;
}
return 0;
@@ -126,13 +154,12 @@ public class Metrics implements Comparable<Metrics> {
}
@Override
- public Metrics clone() {
- return new Metrics(this.ttl, this.savedTime, this.hitsPerTimeInCache);
- }
-
- @Override
public String toString() {
- return "TTL: " + this.ttl + " HpTiC: " + this.hitsPerTimeInCache + " SavedTime: " + this.savedTime;
+ return "TTL: " + this.ttl
+ + " STpTiC: " + this.savedTimePerTimeInCache
+ + " Stales: " + this.stales
+ + " Hits: " + this.hits
+ + " SavedTime: " + this.savedTime;
}
}
diff --git a/src/main/java/br/ufrgs/inf/prosoft/tfcache/Simulator.java b/src/main/java/br/ufrgs/inf/prosoft/tfcache/Simulator.java
index a573181..bdc912b 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/tfcache/Simulator.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/tfcache/Simulator.java
@@ -5,10 +5,18 @@
*/
package br.ufrgs.inf.prosoft.tfcache;
+import br.ufrgs.inf.prosoft.tfcache.configuration.Configuration;
import br.ufrgs.inf.prosoft.tfcache.metadata.Occurrence;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.LongStream;
import java.util.stream.Stream;
/**
@@ -31,30 +39,99 @@ public class Simulator {
simulate(occurrences, ttl, this.metrics);
}
+ public static void simulate(List<Occurrence> occurrences, Metrics metrics) {
+ if (Configuration.getKernel().equals("exhaustive")) {
+ simulate(occurrences, generateAllTTLs(occurrences), metrics);
+ } else {
+ simulate(occurrences, generateTTLsOfInterest(occurrences), metrics);
+ }
+ }
+
+ public static void simulate(List<Occurrence> occurrences, Stream<Long> ttls, Metrics metrics) {
+ ttls.forEach(actualTTL -> {
+ simulate(occurrences.stream(), actualTTL, metrics);
+ });
+ }
+
public static void simulate(Stream<Occurrence> occurrences, long ttl, Metrics metrics) {
Map<String, Long> inputHasCachedTime = new HashMap<>();
+ Map<String, Object> inputHasOutput = new HashMap<>();
- long actualSavedTime = 0;
- long actualHits = 0;
- long actualTimeInCache = 0;
+ long simulationSavedTime = 0;
+ long realSavedTime = 0;
+ long hits = 0;
+ long timeInCache = 0;
+ long stales = 0;
Iterator<Occurrence> iterator = occurrences.iterator();
while (iterator.hasNext()) {
Occurrence occurrence = iterator.next();
- long adjustedStartTime = occurrence.getStartTime() - actualSavedTime;
- long adjustedEndTime = occurrence.getEndTime() - actualSavedTime;
- if (inputHasCachedTime.containsKey(occurrence.getParametersSerialised()) && adjustedStartTime - inputHasCachedTime.get(occurrence.getParametersSerialised()) > ttl) {
- inputHasCachedTime.remove(occurrence.getParametersSerialised());
- }
+ long adjustedStartTime = occurrence.getStartTime() - simulationSavedTime;
+ long adjustedEndTime = occurrence.getEndTime() - simulationSavedTime;
if (inputHasCachedTime.containsKey(occurrence.getParametersSerialised())) {
- actualSavedTime += occurrence.getExecutionTime();
- actualHits++;
+ if (adjustedStartTime - inputHasCachedTime.get(occurrence.getParametersSerialised()) > ttl) {
+ inputHasCachedTime.remove(occurrence.getParametersSerialised());
+ }
+ if (Configuration.getStaleness().equals("shrink")) {
+ if (Objects.deepEquals(inputHasOutput.get(occurrence.getParametersSerialised()), occurrence.getReturnValue())) {
+ realSavedTime += occurrence.getExecutionTime();
+ } else {
+ stales++;
+ }
+ }
+ simulationSavedTime += occurrence.getExecutionTime();
+ hits++;
} else {
inputHasCachedTime.put(occurrence.getParametersSerialised(), adjustedEndTime);
- actualTimeInCache += ttl;
+ if (Configuration.getStaleness().equals("shrink")) {
+ inputHasOutput.put(occurrence.getParametersSerialised(), occurrence.getReturnValue());
+ }
+ timeInCache += ttl;
+ }
+ }
+ if (Configuration.getStaleness().equals("shrink")) {
+ metrics.keepBestMetrics(ttl, hits, timeInCache, stales, realSavedTime);
+ } else {
+ metrics.keepBestMetrics(ttl, hits, timeInCache, stales, simulationSavedTime);
+ }
+ }
+
+ public static Stream<Long> generateTTLsOfInterest(Stream<Occurrence> occurrences) {
+ return generateTTLsOfInterest(occurrences.collect(Collectors.toList()));
+ }
+
+ public static Stream<Long> generateTTLsOfInterest(List<Occurrence> occurrences) {
+ List<Long> windows = new ArrayList<>();
+ for (int i = 1; i < occurrences.size(); i++) {
+ long window = occurrences.get(i).getStartTime() - occurrences.get(i - 1).getEndTime();
+ if (window > 0) {
+ windows.add(window);
+ }
+ }
+
+ Set<Long> ttlsOfInterest = new HashSet<>(windows);
+ for (int hits = 2; hits <= windows.size(); hits++) {
+ for (int shift = 0; shift <= windows.size() - hits; shift++) {
+ long ttl = 0;
+ for (int k = shift; k < shift + hits; k++) {
+ ttl += windows.get(k);
+ }
+ ttlsOfInterest.add(ttl);
+ }
+ }
+ return ttlsOfInterest.stream().parallel();
+ }
+
+ public static Stream<Long> generateAllTTLs(List<Occurrence> occurrences) {
+ long maxTTL = occurrences.get(occurrences.size() - 1).getStartTime() - occurrences.get(0).getEndTime();
+ long minTTL = Long.MAX_VALUE;
+ for (int i = 0; i < occurrences.size() - 1; i++) {
+ long ttl = occurrences.get(i + 1).getStartTime() - occurrences.get(i).getEndTime();
+ if (ttl > 0 && ttl < minTTL) {
+ minTTL = ttl;
}
}
- metrics.keepBestMetrics(ttl, actualHits, actualTimeInCache, actualSavedTime);
+ return LongStream.rangeClosed(minTTL, maxTTL).boxed().parallel();
}
}
diff --git a/src/main/java/br/ufrgs/inf/prosoft/tfcache/TFCache.java b/src/main/java/br/ufrgs/inf/prosoft/tfcache/TFCache.java
index b1a591b..c3b4b39 100755
--- a/src/main/java/br/ufrgs/inf/prosoft/tfcache/TFCache.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/tfcache/TFCache.java
@@ -5,6 +5,7 @@
*/
package br.ufrgs.inf.prosoft.tfcache;
+import br.ufrgs.inf.prosoft.tfcache.configuration.Configuration;
import br.ufrgs.inf.prosoft.tfcache.metadata.Method;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
@@ -33,25 +34,34 @@ public class TFCache {
return this.methods.stream();
}
- private void recommendCacheableMethods(boolean changeable) {
- if (!changeable) {
+ private void recommendCacheableMethods() {
+ if (Configuration.getChangeability().equals("deny")) {
LOGGER.log(Level.INFO, "Removing changeable from {0} methods", this.methods.size());
this.methods.removeIf(Method::isChangeable);
}
LOGGER.log(Level.INFO, "Removing not reusable from {0} methods", this.methods.size());
this.methods.removeIf(Method::isNotReusable);
LOGGER.log(Level.INFO, "Recommending TTL to {0} methods", this.methods.size());
- this.methods.forEach(Method::recommendTTL);
+ this.methods.stream().parallel().forEach(Method::recommendTTL);
+ LOGGER.log(Level.INFO, "Removing not recommended from {0}", this.methods.size());
+ this.methods.removeIf(method -> method.getSavedTime() == 0);
LOGGER.log(Level.INFO, "Ranking {0} methods according saved time", this.methods.size());
this.methods.sort((method1, method2) -> Long.compare(method2.getSavedTime(), method1.getSavedTime()));
LOGGER.log(Level.INFO, "Printing recommendations for {0} methods", this.methods.size());
this.methods.forEach(method -> {
- System.out.println(method.getName() + " Occurrences " + method.getOccurrencesSize() + " Inputs " + method.groupsOfOccurrences().count() + " TTL " + method.getTtl() + " HpTiC " + method.getHitsPerTimeInCache() + " Saves " + method.getSavedTime());
+ System.out.println(method.getName()
+ + " Occurrences " + method.getOccurrencesSize()
+ + " Inputs " + method.groupsOfOccurrences().count()
+ + " TTL " + method.getTtl()
+ + " STpTiC " + method.getSavedTimePerTimeInCache()
+ + " Saves " + method.getSavedTime()
+ + " Hits " + method.getBestMetrics().getHits()
+ + " Stales " + method.getBestMetrics().getStales());
});
}
- private void recommendCacheableInputs(boolean changeable, String outputPath) {
- if (!changeable) {
+ private void recommendCacheableInputs() {
+ if (Configuration.getChangeability().equals("deny")) {
LOGGER.log(Level.INFO, "Removing changeable inputs from {0} methods", this.methods.size());
this.methods.forEach(Method::removeChangeableInputs);
}
@@ -60,18 +70,35 @@ public class TFCache {
LOGGER.log(Level.INFO, "Removing not reusable methods from {0} methods", this.methods.size());
this.methods.removeIf(method -> method.groupsOfOccurrences().count() < 1);
LOGGER.log(Level.INFO, "Recommending TTL to {0} methods", this.methods.size());
- this.methods.forEach(Method::recommendTTLPerInput);
+ this.methods.stream().parallel().forEach(Method::recommendTTLPerInput);
+ LOGGER.log(Level.INFO, "Removing not recommended inputs from {0}", this.methods.size());
+ this.methods.forEach(Method::removeNotRecommededInputs);
+ LOGGER.log(Level.INFO, "Removing not recommended methods from {0}", this.methods.size());
+ this.methods.removeIf(method -> method.groupsOfOccurrences().count() < 1);
LOGGER.log(Level.INFO, "Ranking {0} methods and inputs according saved time", this.methods.size());
this.methods.forEach(Method::rankRecommendations);
this.methods.sort((method1, method2) -> Long.compare(method2.getSavedTime(), method1.getSavedTime()));
LOGGER.log(Level.INFO, "Printing recommendations for {0} methods", this.methods.size());
this.methods.forEach(method -> {
- System.out.println(method.getName() + " Occurrences " + method.getOccurrencesSize() + " Inputs " + method.groupsOfOccurrences().count() + " TTL " + method.getTtl() + " HpTiC " + method.getHitsPerTimeInCache() + " Saves " + method.getSavedTime());
+ System.out.println(method.getName()
+ + " Occurrences " + method.getOccurrencesSize()
+ + " Inputs " + method.groupsOfOccurrences().count()
+ + " TTL " + method.getTtl()
+ + " STpTiC " + method.getSavedTimePerTimeInCache()
+ + " Saves " + method.getSavedTime()
+ + " Hits " + method.getBestMetrics().getHits()
+ + " Stales " + method.getBestMetrics().getStales());
method.groupsOfOccurrences().forEach(group -> {
- System.out.println("\t" + group.getParameters().hashCode() + " Occurrences " + group.getOccurrencesSize() + " -> TTL " + group.getTtl() + " HpTiC " + group.getHitsPerTimeInCache() + " Saves " + group.getSavedTime());
+ System.out.println("\t" + group.getParameters().hashCode()
+ + " Occurrences " + group.getOccurrencesSize()
+ + " -> TTL " + group.getTtl()
+ + " STpTiC " + group.getSavedTimePerTimeInCache()
+ + " Saves " + group.getSavedTime()
+ + " Hits " + group.getBestMetrics().getHits()
+ + " Stales " + group.getBestMetrics().getHits());
});
});
- try (FileWriter fileWriter = new FileWriter(outputPath)) {
+ try (FileWriter fileWriter = new FileWriter(Configuration.getOutput())) {
JsonObject jsonCacheableParameters = new JsonObject();
this.methods.forEach(method -> {
JsonObject cacheableParameters = new JsonObject();
@@ -88,22 +115,10 @@ public class TFCache {
}
public void recommend() {
- recommend(false);
- }
-
- public void recommend(String outputPath) {
- recommend(false, outputPath);
- }
-
- public void recommend(boolean changeable) {
- recommendCacheableMethods(changeable);
- }
-
- public void recommend(boolean changeable, String outputPath) {
- if (outputPath == null) {
- recommend(changeable);
+ if (Configuration.getLevel().equals("method")) {
+ recommendCacheableMethods();
} else {
- recommendCacheableInputs(changeable, outputPath);
+ recommendCacheableInputs();
}
}