tfcache
Changes
src/main/java/br/ufrgs/inf/prosoft/tfcache/Simulator.java 293(+129 -164)
src/main/java/br/ufrgs/inf/prosoft/tfcache/TFCache.java 207(+94 -113)
Details
diff --git a/src/main/java/br/ufrgs/inf/prosoft/tfcache/configuration/Arguments.java b/src/main/java/br/ufrgs/inf/prosoft/tfcache/configuration/Arguments.java
index 8d7d6bd..f39042b 100755
--- a/src/main/java/br/ufrgs/inf/prosoft/tfcache/configuration/Arguments.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/tfcache/configuration/Arguments.java
@@ -7,18 +7,13 @@ import java.util.stream.Stream;
public class Arguments {
public static Map<String, String> parse(String[] args) {
- Map<String, String> arguments = Stream.of(args).map(arg -> {
+ return Stream.of(args).map(arg -> {
arg = arg.replaceFirst("--", "");
int indexOf = arg.indexOf("=");
if (indexOf == -1) {
return new String[]{arg, ""};
}
return new String[]{arg.substring(0, indexOf), arg.substring(indexOf + 1)};
- }).collect(Collectors.toMap(array -> {
- return array[0];
- }, array -> {
- return array[1];
- }));
- return arguments;
+ }).collect(Collectors.toMap(array -> array[0], array -> array[1]));
}
}
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
index 0c64f2d..f4ae3b7 100755
--- a/src/main/java/br/ufrgs/inf/prosoft/tfcache/configuration/Configuration.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/tfcache/configuration/Configuration.java
@@ -19,7 +19,7 @@ public class Configuration {
private static String changeability = "allow";
private static String staleness = "ignore";
private static String kernel = "exhaustive";
- private static ArrayList<Double> preferences = new ArrayList<>(List.of(1D, 0D));
+ private static final ArrayList<Double> preferences = new ArrayList<>(List.of(1D, 0D));
private static boolean verbose = false;
public static void process(String[] args) {
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 b385b41..d50ca71 100755
--- a/src/main/java/br/ufrgs/inf/prosoft/tfcache/Main.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/tfcache/Main.java
@@ -25,15 +25,15 @@ 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> " +
- "[--store=<storePath>] " +
- "[--level=<method|input>] " +
- "[--output=<outputPath>] " +
- "[--changeability=<allow|deny>] " +
- "[--staleness=<ignore|shrink>] " +
- "[--kernel=<exhaustive|optimised>|test] " +
- "[--preferences=(savedTime)0..1,0..1(idleTime)] " +
- "[--verbose=<false|true>]");
+ System.err.println("--trace=<TracePath>" +
+ " [--store=<storePath>]" +
+ " [--level=<method|input>]" +
+ " [--output=<outputPath>]" +
+ " [--changeability=<allow|deny>]" +
+ " [--staleness=<ignore|shrink>]" +
+ " [--kernel=<exhaustive|optimised>|test]" +
+ " [--preferences=(savedTime)0..1,0..1(idleTime)]" +
+ " [--verbose=<false|true>]");
System.exit(1);
}
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 65d1d7d..9a0202c 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
@@ -1,8 +1,3 @@
-/*
- * 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.tfcache.metadata;
import br.ufrgs.inf.prosoft.tfcache.Metrics;
@@ -10,7 +5,6 @@ import br.ufrgs.inf.prosoft.tfcache.Pareto;
import br.ufrgs.inf.prosoft.tfcache.Simulator;
import br.ufrgs.inf.prosoft.tfcache.configuration.Configuration;
-import java.math.BigDecimal;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
@@ -19,89 +13,59 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Stream;
-/**
- *
- * @author romulo
- */
public class GroupOfOccurrences {
- private static final Logger LOGGER = Logger.getLogger(GroupOfOccurrences.class.getName());
+ private static final Logger LOGGER = Logger.getLogger(GroupOfOccurrences.class.getName());
+ private final List<Occurrence> occurrences;
+ private final String parameters;
+ private Pareto pareto;
- private final List<Occurrence> occurrences;
- private final String parameters;
+ public GroupOfOccurrences(String parameters, List<Occurrence> occurrences) {
+ this.parameters = parameters;
+ this.occurrences = occurrences;
+ }
- private Pareto pareto;
+ public String getParameters() {
+ return this.parameters;
+ }
- public GroupOfOccurrences(String parameters, List<Occurrence> occurrences) {
- this.parameters = parameters;
- this.occurrences = occurrences;
+ public Metrics getBestMetrics() {
+ if (this.pareto == null) {
+ throw new RuntimeException("simulation must be executed");
}
-
- public String getParameters() {
- return this.parameters;
+ return this.pareto.getBestMetrics();
+ }
+
+ public Stream<Occurrence> occurrences() {
+ return this.occurrences.stream();
+ }
+
+ public boolean isChangeable() {
+ Iterator<Occurrence> iterator = this.occurrences.iterator();
+ Occurrence first = iterator.next();
+ while (iterator.hasNext()) {
+ Occurrence next = iterator.next();
+ if (!Objects.deepEquals(first.getReturnValue(), next.getReturnValue())) {
+ return true;
+ }
}
+ return false;
+ }
- public int getOccurrencesSize() {
- return this.occurrences.size();
+ public void calculateMetrics() {
+ if (this.pareto != null) {
+ LOGGER.log(Level.WARNING, "metrics already calculated");
}
-
- public Metrics getBestMetrics() {
- if (this.pareto == null) {
- throw new RuntimeException("simulation must be executed");
- }
- return this.pareto.getBestMetrics();
+ if (this.occurrences.size() < 2) {
+ throw new RuntimeException("Not reusable input");
}
-
- public long getTtl() {
- return getBestMetrics().getTtl();
- }
-
- public long getHits() {
- return getBestMetrics().getHits();
- }
-
- public long getStales() {
- return getBestMetrics().getStales();
- }
-
- public double getSavedTime() {
- return getBestMetrics().getSavedTime();
- }
-
- public BigDecimal getSavedTimePerTimeInCache() {
- return getBestMetrics().getSavedTimePerTimeInCache();
- }
-
- public Stream<Occurrence> occurrences() {
- return this.occurrences.stream();
- }
-
- public boolean isChangeable() {
- Iterator<Occurrence> iterator = this.occurrences.iterator();
- Occurrence first = iterator.next();
- while (iterator.hasNext()) {
- Occurrence next = iterator.next();
- if (!Objects.deepEquals(first.getReturnValue(), next.getReturnValue())) {
- return true;
- }
- }
- return false;
- }
-
- public void calculateMetrics() {
- if (this.pareto != null) {
- LOGGER.log(Level.WARNING, "metrics already calculated");
- }
- if (this.occurrences.size() < 2) {
- throw new RuntimeException("Not reusable input");
- }
- this.occurrences.sort(Comparator.comparingLong(Occurrence::getStartTime));
- this.pareto = new Pareto();
- Simulator.simulate(this.occurrences, this.pareto);
- if (Configuration.getVerbose()) {
- this.pareto.values().forEach(it ->
- System.out.println(Configuration.getInput() + "," + it.getTtl() + "," + it.getSavedTime() + "," + it.getHits() + "," + it.getTimeInCache()));
- }
+ this.occurrences.sort(Comparator.comparingLong(Occurrence::getStartTime));
+ this.pareto = new Pareto();
+ Simulator.simulate(this.occurrences, this.pareto);
+ if (Configuration.getVerbose()) {
+ this.pareto.values().forEach(it ->
+ System.out.println(Configuration.getInput() + "," + it.getTtl() + "," + it.getSavedTime() + "," + it.getHits() + "," + it.getTimeInCache()));
}
+ }
}
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 84fd1aa..4071323 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
@@ -1,8 +1,3 @@
-/*
- * 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.tfcache.metadata;
import br.ufrgs.inf.prosoft.tfcache.Metrics;
@@ -11,237 +6,159 @@ import br.ufrgs.inf.prosoft.tfcache.Simulator;
import br.ufrgs.inf.prosoft.tfcache.StorageManager;
import br.ufrgs.inf.prosoft.tfcache.configuration.Configuration;
-import java.math.BigDecimal;
+import java.text.MessageFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
-import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
-/**
- * @author romulo
- */
public class Method {
- private static final Logger LOGGER = Logger.getLogger(Method.class.getName());
-
- private final String name;
- private final List<Occurrence> occurrences;
- private List<GroupOfOccurrences> groupsOfOccurrences;
-
- private Integer countChangeableGroups;
-
- private Pareto pareto;
-
- public Method(String name, List<Occurrence> occurrences) {
- this.name = name;
- if (occurrences == null) {
- throw new RuntimeException("Occurrences is null");
- }
- if (occurrences.isEmpty()) {
- throw new RuntimeException("Occurrences is empty");
- }
- this.occurrences = occurrences;
- }
-
- public static Map<String, List<Occurrence>> groupByInput(List<Occurrence> occurrences) {
- if (occurrences == null) {
- throw new RuntimeException("Occurrences cannot be null");
- }
- Map<String, List<Occurrence>> inputHasOccurrences = new ConcurrentHashMap<>();
- occurrences.forEach(occurrence -> {
- String parameters = occurrence.getParametersSerialised();
-
- inputHasOccurrences.compute(parameters, (key, oldValue) -> {
- if (oldValue == null) {
- oldValue = new ArrayList<>();
- }
- oldValue.add(occurrence);
- return oldValue;
- });
- });
- return inputHasOccurrences;
- }
-
- public String getName() {
- return name;
- }
-
- public Metrics getBestMetrics() {
- return this.pareto.getBestMetrics();
- }
-
- public double getEstimatedSavedTime() {
- if (getBestMetrics() != null) {
- return getBestMetrics().getSavedTime();
- }
- return groupsOfOccurrences().map(GroupOfOccurrences::getSavedTime).reduce(Double::sum).orElse(0D);
- }
-
- public BigDecimal getEstimatedSavedTimePerTimeInCache() {
- if (getBestMetrics() != null) {
- return getBestMetrics().getSavedTimePerTimeInCache();
- }
- GroupOfOccurrences max = groupsOfOccurrences().max(Comparator.comparing(GroupOfOccurrences::getSavedTimePerTimeInCache)).orElseThrow();
- return max.getSavedTimePerTimeInCache();
- }
-
- public Stream<Occurrence> occurrences() {
- if (this.occurrences == null) {
- throw new RuntimeException("Occurrences already consumed");
- }
- return this.occurrences.stream();
- }
-
- public int getOccurrencesSize() {
- if (this.occurrences == null) {
- if (this.groupsOfOccurrences == null) {
- throw new RuntimeException("groupsOfOccurrences is null");
- }
- return this.groupsOfOccurrences.stream().map(GroupOfOccurrences::getOccurrencesSize).reduce(Integer::sum).orElse(0);
- }
- return this.occurrences.size();
- }
-
- public Stream<GroupOfOccurrences> groupsOfOccurrences() {
- if (this.groupsOfOccurrences == null) {
- groupByInput();
- }
- return this.groupsOfOccurrences.stream();
- }
-
- private void groupByInput() {
- if (this.occurrences == null) {
- throw new RuntimeException("Occurrences already consumed");
- }
- this.groupsOfOccurrences = groupByInput(this.occurrences).entrySet().stream()
- .map(entry -> new GroupOfOccurrences(entry.getKey(), entry.getValue()))
- .collect(Collectors.toList());
- }
-
- public void removeChangeableInputs() {
- if (this.countChangeableGroups != null) {
- throw new RuntimeException("Changeable already filtered");
- }
- if (this.groupsOfOccurrences == null) {
- groupByInput();
- }
- int initialCountOfInputs = this.groupsOfOccurrences.size();
- this.groupsOfOccurrences.removeIf(GroupOfOccurrences::isChangeable);
- this.countChangeableGroups = initialCountOfInputs - this.groupsOfOccurrences.size();
- if (this.countChangeableGroups > 0) {
- LOGGER.log(Level.INFO, "\tRemoved {0} of {1} changeable inputs from method {2}", new Object[]{this.countChangeableGroups, initialCountOfInputs, this.name});
- }
- }
-
- public boolean isChangeable() {
- if (this.countChangeableGroups != null) {
- return this.countChangeableGroups > 0;
- }
- if (this.groupsOfOccurrences != null) {
- return this.groupsOfOccurrences.stream().anyMatch(GroupOfOccurrences::isChangeable);
- }
- Map<String, Object> inputHasOutput = new HashMap<>();
- for (Occurrence occurrence : this.occurrences) {
- String parameters = occurrence.getParametersSerialised();
- if (!inputHasOutput.containsKey(parameters)) {
- inputHasOutput.put(parameters, occurrence.getReturnValue());
- } else if (!Objects.deepEquals(inputHasOutput.get(parameters), occurrence.getReturnValue())) {
- return true;
- }
- }
- return false;
- }
-
- public void removeSingleOccurrences() {
- if (this.groupsOfOccurrences == null) {
- groupByInput();
- }
- int initialCountofOccurrences = this.groupsOfOccurrences.size();
- this.groupsOfOccurrences.removeIf(groupOfOccurrences -> groupOfOccurrences.getOccurrencesSize() < 2);
- 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});
- }
- }
-
- public boolean isReusable() {
- if (this.groupsOfOccurrences != null) {
- return this.groupsOfOccurrences.stream().anyMatch(groupOfOccurrences -> groupOfOccurrences.getOccurrencesSize() > 1);
- }
- Map<String, Long> inputHasFrequency = occurrences()
- .map(Occurrence::getParametersSerialised)
- .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
- return inputHasFrequency.values().stream().anyMatch(frequency -> frequency > 1);
- }
-
- public boolean isNotReusable() {
- return !isReusable();
- }
-
- public void recommendTTL() {
- if (this.pareto != null) {
- LOGGER.log(Level.WARNING, "metrics already calculated");
- }
- if (this.occurrences == null) {
- throw new RuntimeException("groupByInputs called. Cannot proceed");
- }
- this.pareto = new Pareto();
- if (this.occurrences.size() < 2) {
- return;
- }
- this.occurrences.sort(Comparator.comparingLong(Occurrence::getStartTime));
- Simulator.simulate(this.occurrences, this.pareto);
- if (Configuration.getVerbose()) {
- String application = Configuration.getInput().split(",")[0];
- this.pareto.values().forEach(it ->
- System.out.println(application + "," + name + "," + it.getTtl() + "," + it.getSavedTime() + "," + it.getHits() + "," + it.getTimeInCache()));
- }
- }
-
- public void recommendTTLPerInput() {
- if (this.groupsOfOccurrences == null) {
- groupByInput();
- removeSingleOccurrences();
- }
- if (Configuration.getVerbose()) {
- System.out.println("=== " + getName() + " ===");
- Configuration.setInput(Configuration.getInput().split(",")[0] + "," + getName() + ",");
- groupsOfOccurrences().forEach(GroupOfOccurrences::calculateMetrics);
- } else {
- groupsOfOccurrences().parallel().forEach(GroupOfOccurrences::calculateMetrics);
- }
- String uuid = Configuration.getUUID().replace("level:input", "level:method");
- Pareto pareto = StorageManager.get(uuid, this.occurrences);
- if (this.pareto == null && pareto != null) {
- this.pareto = pareto;
- }
- }
-
- public void removeNotRecommendedInputs() {
- if (this.groupsOfOccurrences == 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});
- }
- }
-
- public void rankRecommendations() {
- if (this.groupsOfOccurrences == null) {
- throw new RuntimeException("groupsOfOccurrences is null");
- }
- this.groupsOfOccurrences.sort((group1, group2) -> group2.getSavedTimePerTimeInCache().compareTo(group1.getSavedTimePerTimeInCache()));
- }
-
- @Override
- public String toString() {
- return this.name;
- }
+ private static final Logger LOGGER = Logger.getLogger(Method.class.getName());
+ private final String name;
+ private final List<Occurrence> occurrences;
+ private List<GroupOfOccurrences> groupsOfOccurrences;
+ private Integer countChangeableGroups;
+ private Pareto pareto;
+
+ public Method(String name, List<Occurrence> occurrences) {
+ this.name = name;
+ if (occurrences == null) throw new RuntimeException("Occurrences is null");
+ if (occurrences.isEmpty()) throw new RuntimeException("Occurrences is empty");
+ this.occurrences = occurrences;
+ }
+
+ public static Map<String, List<Occurrence>> groupByInput(List<Occurrence> occurrences) {
+ Map<String, List<Occurrence>> inputHasOccurrences = new ConcurrentHashMap<>();
+ occurrences.forEach(occurrence -> {
+ String parameters = occurrence.getParametersSerialised();
+ inputHasOccurrences.compute(parameters, (key, oldValue) -> {
+ if (oldValue == null) oldValue = new ArrayList<>();
+ oldValue.add(occurrence);
+ return oldValue;
+ });
+ });
+ return inputHasOccurrences;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Metrics getBestMetrics() {
+ if (this.pareto == null) throw new RuntimeException("trying to access pareto before calculating it");
+ return this.pareto.getBestMetrics();
+ }
+
+ public double getEstimatedSavedTime() {
+ if (getBestMetrics() != null) return getBestMetrics().getSavedTime();
+ return groupsOfOccurrences().map(it -> it.getBestMetrics().getSavedTime()).reduce(Double::sum).orElse(0D);
+ }
+
+ public Stream<Occurrence> occurrences() {
+ return this.occurrences.stream();
+ }
+
+ public Stream<GroupOfOccurrences> groupsOfOccurrences() {
+ if (this.groupsOfOccurrences == null) groupByInput();
+ return this.groupsOfOccurrences.stream();
+ }
+
+ private void groupByInput() {
+ this.groupsOfOccurrences = groupByInput(this.occurrences).entrySet().stream()
+ .map(entry -> new GroupOfOccurrences(entry.getKey(), entry.getValue()))
+ .collect(Collectors.toList());
+ }
+
+ public void removeChangeableInputs() {
+ if (this.countChangeableGroups != null) throw new RuntimeException("Changeable already filtered");
+ if (this.groupsOfOccurrences == null) groupByInput();
+ int initialCountOfInputs = this.groupsOfOccurrences.size();
+ this.groupsOfOccurrences.removeIf(GroupOfOccurrences::isChangeable);
+ this.countChangeableGroups = initialCountOfInputs - this.groupsOfOccurrences.size();
+ if (this.countChangeableGroups > 0)
+ LOGGER.info(MessageFormat.format("\tRemoved {0} of {1} changeable inputs from method {2}", this.countChangeableGroups, initialCountOfInputs, this.name));
+ }
+
+ public boolean isChangeable() {
+ if (this.countChangeableGroups != null) return this.countChangeableGroups > 0;
+ if (this.groupsOfOccurrences != null) return this.groupsOfOccurrences.stream().anyMatch(GroupOfOccurrences::isChangeable);
+ Map<String, Object> inputHasOutput = new HashMap<>();
+ for (Occurrence occurrence : this.occurrences) {
+ String parameters = occurrence.getParametersSerialised();
+ if (!inputHasOutput.containsKey(parameters)) inputHasOutput.put(parameters, occurrence.getReturnValue());
+ else if (!Objects.deepEquals(inputHasOutput.get(parameters), occurrence.getReturnValue())) return true;
+ }
+ return false;
+ }
+
+ public void removeSingleOccurrences() {
+ if (this.groupsOfOccurrences == null) groupByInput();
+ int initialCountOfOccurrences = this.groupsOfOccurrences.size();
+ this.groupsOfOccurrences.removeIf(it -> it.occurrences().count() < 2);
+ int removedOccurrences = initialCountOfOccurrences - this.groupsOfOccurrences.size();
+ if (removedOccurrences > 0) LOGGER.info(MessageFormat.format("\tRemoved {0} of {1} inputs from method {2}", removedOccurrences, initialCountOfOccurrences, this.name));
+ }
+
+ public boolean isReusable() {
+ if (this.groupsOfOccurrences != null) return this.groupsOfOccurrences.stream().anyMatch(it -> it.occurrences().count() > 1);
+ Map<String, Long> inputHasFrequency = occurrences()
+ .map(Occurrence::getParametersSerialised)
+ .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
+ return inputHasFrequency.values().stream().anyMatch(frequency -> frequency > 1);
+ }
+
+ public boolean isNotReusable() {
+ return !isReusable();
+ }
+
+ public void recommendTTL() {
+ if (this.pareto != null) LOGGER.warning("metrics already calculated");
+ this.pareto = new Pareto();
+ if (this.occurrences.size() < 2) return;
+ this.occurrences.sort(Comparator.comparingLong(Occurrence::getStartTime));
+ Simulator.simulate(this.occurrences, this.pareto);
+ if (Configuration.getVerbose()) {
+ String application = Configuration.getInput().split(",")[0];
+ this.pareto.values().forEach(it -> System.out.println(application + "," + name + "," + it.getTtl() + "," + it.getSavedTime() + "," + it.getHits() + "," + it.getTimeInCache()));
+ }
+ }
+
+ public void recommendTTLPerInput() {
+ if (this.groupsOfOccurrences == null) {
+ groupByInput();
+ removeSingleOccurrences();
+ }
+ if (Configuration.getVerbose()) {
+ System.out.println("=== " + getName() + " ===");
+ Configuration.setInput(Configuration.getInput().split(",")[0] + "," + getName() + ",");
+ groupsOfOccurrences().forEach(GroupOfOccurrences::calculateMetrics);
+ } else {
+ groupsOfOccurrences().parallel().forEach(GroupOfOccurrences::calculateMetrics);
+ }
+ String uuid = Configuration.getUUID().replace("level:input", "level:method");
+ Pareto pareto = StorageManager.get(uuid, this.occurrences);
+ if (this.pareto == null && pareto != null) this.pareto = pareto;
+ }
+
+ public void removeNotRecommendedInputs() {
+ if (this.groupsOfOccurrences == null) throw new RuntimeException("Recommendations not called");
+ int initialCountOfOccurrences = this.groupsOfOccurrences.size();
+ this.groupsOfOccurrences.removeIf(it -> it.getBestMetrics().getSavedTime() == 0);
+ int removedOccurrences = initialCountOfOccurrences - this.groupsOfOccurrences.size();
+ if (removedOccurrences > 0) LOGGER.info(MessageFormat.format("\tRemoved {0} of {1} inputs from method {2}", removedOccurrences, initialCountOfOccurrences, this.name));
+ }
+
+ public void rankRecommendations() {
+ if (this.groupsOfOccurrences == null) throw new RuntimeException("groupsOfOccurrences is null");
+ this.groupsOfOccurrences.sort((group1, group2) -> Double.compare(group2.getBestMetrics().getSavedTime(), group1.getBestMetrics().getSavedTime()));
+ }
+
+ @Override
+ public String toString() {
+ return 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 db1120b..d230722 100755
--- a/src/main/java/br/ufrgs/inf/prosoft/tfcache/Metrics.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/tfcache/Metrics.java
@@ -71,11 +71,11 @@ public class Metrics implements Comparable<Metrics> {
return Math.sqrt(Math.pow(x1 - x2, 2) - Math.pow(y1, y2));
}
- public double calculateEuclideanDistance(double objectiveSavedTime, double objectiveIdleTime) {
+ protected double calculateEuclideanDistance(double objectiveSavedTime, double objectiveIdleTime) {
return calculateEuclideanDistance(getSavedTime(), getIdleTime(), objectiveSavedTime, objectiveIdleTime);
}
- public String getUUID() {
+ protected String getUUID() {
return uuid;
}
@@ -122,7 +122,7 @@ public class Metrics implements Comparable<Metrics> {
return Configuration.getPreferences().get(0) * getSavedTime() - Configuration.getPreferences().get(1) * getIdleTime();
}
- public Metrics getNormalised(double savedTime, double idleTime) {
+ protected Metrics getNormalised(double savedTime, double idleTime) {
if (savedTime < 0 || savedTime > 1) {
throw new RuntimeException("wrong savedTime");
}
diff --git a/src/main/java/br/ufrgs/inf/prosoft/tfcache/Pareto.java b/src/main/java/br/ufrgs/inf/prosoft/tfcache/Pareto.java
old mode 100644
new mode 100755
index 065a9a7..edfb7da
--- a/src/main/java/br/ufrgs/inf/prosoft/tfcache/Pareto.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/tfcache/Pareto.java
@@ -9,81 +9,83 @@ import java.util.stream.Stream;
public class Pareto {
- private final Map<Double, Metrics> savedTimeHasMetrics;
-
- public Pareto() {
- savedTimeHasMetrics = new ConcurrentHashMap<>();
- }
-
- public Pareto(List<Metrics> metrics) {
- this();
- metrics.forEach(this::addIfPareto);
- }
-
- public static void removeDominatedMetrics(Collection<Metrics> allMetrics) {
- Map<Double, List<Metrics>> groupBySavedTime = allMetrics.stream().collect(Collectors.groupingBy(Metrics::getSavedTime));
- groupBySavedTime.remove(0L);
- groupBySavedTime.forEach((savedTime, metrics) -> {
- double minIdleTime = metrics.stream().mapToDouble(Metrics::getIdleTime).min().orElse(0);
- metrics.removeIf(metric -> metric.getIdleTime() > minIdleTime);
- });
-
- List<Metrics> localMaxima = groupBySavedTime.values().stream()
- .map(Collection::stream)
- .reduce(Stream::concat)
- .orElse(Stream.empty())
- .collect(Collectors.toList());
-
- allMetrics.removeIf(metrics -> !localMaxima.contains(metrics));
- }
-
- public synchronized void addIfPareto(Metrics metrics) {
- if (metrics.getSavedTime() == 0) {
- return;
- }
- savedTimeHasMetrics.merge(metrics.getSavedTime(), metrics, (existing, incoming) -> existing.getIdleTime() < incoming.getIdleTime() ? existing : incoming);
+ private final Map<Double, Metrics> savedTimeHasMetrics;
+ private Metrics bestMetrics;
+
+ public Pareto() {
+ savedTimeHasMetrics = new ConcurrentHashMap<>();
+ }
+
+ public Pareto(List<Metrics> metrics) {
+ this();
+ metrics.forEach(this::addIfPareto);
+ }
+
+ public static void removeDominatedMetrics(Collection<Metrics> allMetrics) {
+ Map<Double, List<Metrics>> groupBySavedTime = allMetrics.stream().collect(Collectors.groupingBy(Metrics::getSavedTime));
+ groupBySavedTime.remove(0D);
+ groupBySavedTime.forEach((savedTime, metrics) -> {
+ double minIdleTime = metrics.stream().mapToDouble(Metrics::getIdleTime).min().orElse(0);
+ metrics.removeIf(metric -> metric.getIdleTime() > minIdleTime);
+ });
+
+ List<Metrics> localMaxima = groupBySavedTime.values().stream()
+ .map(Collection::stream)
+ .reduce(Stream::concat)
+ .orElse(Stream.empty())
+ .collect(Collectors.toList());
+
+ allMetrics.removeIf(metrics -> !localMaxima.contains(metrics));
+ }
+
+ public synchronized void addIfPareto(Metrics metrics) {
+ if (metrics.getSavedTime() == 0) {
+ return;
}
-
- public Collection<Metrics> values() {
- return savedTimeHasMetrics.values();
- }
-
- public Set<Long> getTtls() {
- return values().stream().map(Metrics::getTtl).collect(Collectors.toSet());
+ savedTimeHasMetrics.merge(metrics.getSavedTime(), metrics, (existing, incoming) -> existing.getIdleTime() < incoming.getIdleTime() ? existing : incoming);
+ }
+
+ public Collection<Metrics> values() {
+ return savedTimeHasMetrics.values();
+ }
+
+ public Set<Long> getTtls() {
+ return values().stream().map(Metrics::getTtl).collect(Collectors.toSet());
+ }
+
+ public Stream<Metrics> getNormalised() {
+ double minSavedTime = values().stream().mapToDouble(Metrics::getSavedTime).min().orElseThrow();
+ double maxSavedTime = values().stream().mapToDouble(Metrics::getSavedTime).max().orElseThrow();
+ double distanceSavedTime = maxSavedTime - minSavedTime;
+ double minIdleTime = values().stream().mapToDouble(Metrics::getIdleTime).min().orElseThrow();
+ double maxIdleTime = values().stream().mapToDouble(Metrics::getIdleTime).max().orElseThrow();
+ double distanceIdleTime = maxIdleTime - minIdleTime;
+
+ return values().stream().map(it -> {
+ double normalisedSavedTime = (it.getSavedTime() - minSavedTime) / distanceSavedTime;
+ double normalisedIdleTime = (it.getIdleTime() - minIdleTime) / distanceIdleTime;
+ return it.getNormalised(normalisedSavedTime, normalisedIdleTime);
+ });
+ }
+
+ public Metrics getBestMetrics() {
+ if (this.bestMetrics == null) this.bestMetrics = getBestMetrics(Configuration.getPreferences().get(0), Configuration.getPreferences().get(1));
+ return this.bestMetrics;
+ }
+
+ private Metrics getBestMetrics(double percentageObjectiveSavedTime, double percentageObjectiveIdleTime) {
+ if (percentageObjectiveSavedTime < 0 || percentageObjectiveSavedTime > 1) {
+ throw new RuntimeException("invalid objective saved time");
}
-
- public Stream<Metrics> getNormalised() {
- double minSavedTime = values().stream().mapToDouble(Metrics::getSavedTime).min().orElseThrow();
- double maxSavedTime = values().stream().mapToDouble(Metrics::getSavedTime).max().orElseThrow();
- double distanceSavedTime = maxSavedTime - minSavedTime;
- double minIdleTime = values().stream().mapToDouble(Metrics::getIdleTime).min().orElseThrow();
- double maxIdleTime = values().stream().mapToDouble(Metrics::getIdleTime).max().orElseThrow();
- double distanceIdleTime = maxIdleTime - minIdleTime;
-
- return values().stream().map(it -> {
- double normalisedSavedTime = (it.getSavedTime() - minSavedTime) / distanceSavedTime;
- double normalisedIdleTime = (it.getIdleTime() - minIdleTime) / distanceIdleTime;
- return it.getNormalised(normalisedSavedTime, normalisedIdleTime);
- });
+ if (percentageObjectiveIdleTime < 0 || percentageObjectiveIdleTime > 1) {
+ throw new RuntimeException("invalid objective idle time");
}
-
- public Metrics getBestMetrics() {
- return getBestMetrics(Configuration.getPreferences().get(0), Configuration.getPreferences().get(1));
- }
-
- private Metrics getBestMetrics(double percentageObjectiveSavedTime, double percentageObjectiveIdleTime) {
- if (percentageObjectiveSavedTime < 0 || percentageObjectiveSavedTime > 1) {
- throw new RuntimeException("invalid objective saved time");
- }
- if (percentageObjectiveIdleTime < 0 || percentageObjectiveIdleTime > 1) {
- throw new RuntimeException("invalid objective idle time");
- }
- if (savedTimeHasMetrics.isEmpty()) {
- return new Metrics();
- }
- double minIdleTime = values().stream().mapToDouble(Metrics::getIdleTime).min().orElseThrow() * percentageObjectiveIdleTime;
- double maxSavedTime = values().stream().mapToDouble(Metrics::getSavedTime).max().orElseThrow() * percentageObjectiveSavedTime;
- return values().stream().min(Comparator.comparingDouble(it -> it.calculateEuclideanDistance(maxSavedTime, minIdleTime))).orElseThrow();
+ if (savedTimeHasMetrics.isEmpty()) {
+ return new Metrics();
}
+ double minIdleTime = values().stream().mapToDouble(Metrics::getIdleTime).min().orElseThrow() * percentageObjectiveIdleTime;
+ double maxSavedTime = values().stream().mapToDouble(Metrics::getSavedTime).max().orElseThrow() * percentageObjectiveSavedTime;
+ return values().stream().min(Comparator.comparingDouble(it -> it.calculateEuclideanDistance(maxSavedTime, minIdleTime))).orElseThrow();
+ }
}
src/main/java/br/ufrgs/inf/prosoft/tfcache/Simulator.java 293(+129 -164)
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 a17aae1..7744b76 100755
--- a/src/main/java/br/ufrgs/inf/prosoft/tfcache/Simulator.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/tfcache/Simulator.java
@@ -1,8 +1,3 @@
-/*
- * 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.tfcache;
import br.ufrgs.inf.prosoft.tfcache.configuration.Configuration;
@@ -19,175 +14,145 @@ import java.util.stream.Stream;
*/
public class Simulator {
- private final Pareto pareto;
-
- public Simulator() {
- this.pareto = new Pareto();
- }
-
- public static void simulate(List<Occurrence> occurrences, Pareto pareto) {
- Pareto computeIfAbsent = StorageManager.computeIfAbsent(occurrences, () -> {
- switch (Configuration.getKernel()) {
- case "exhaustive":
- simulate(occurrences, generateAllTTLs(occurrences), pareto);
- break;
- case "optimised":
- simulate(occurrences, generateTTLsOfInterest(occurrences), pareto);
- break;
- default:
- testKernels(occurrences);
- break;
- }
- return pareto;
- });
- computeIfAbsent.values().forEach(pareto::addIfPareto);
- }
-
- public static void simulate(List<Occurrence> occurrences, Stream<Long> ttls, Pareto pareto) {
- ttls.forEach(actualTTL -> simulate(occurrences.stream(), actualTTL, pareto));
- }
-
- public static void simulate(Stream<Occurrence> occurrences, long ttl, Pareto pareto) {
- Map<String, Long> inputHasCachedTime = new HashMap<>();
- Map<String, Object> inputHasOutput = new HashMap<>();
-
- long blindedSavedTime = 0;
- long realSavedTime = 0;
- long hits = 0;
- long computationTime = 0;
- long timeInCache = 0;
- long stales = 0;
-
- Iterator<Occurrence> iterator = occurrences.iterator();
- while (iterator.hasNext()) {
- Occurrence occurrence = iterator.next();
- long adjustedStartTime = occurrence.getStartTime() - blindedSavedTime;
- long adjustedEndTime = occurrence.getEndTime() - blindedSavedTime;
- if (occurrence.getExecutionTime() < 0) {
- throw new RuntimeException("executionTime cannot be under zero");
- }
- if (adjustedEndTime < adjustedStartTime) {
- throw new RuntimeException("adjustedEndTime should not be lesser than adjustedStartTime");
- }
- if (inputHasCachedTime.containsKey(occurrence.getParametersSerialised()) &&
- adjustedStartTime - inputHasCachedTime.get(occurrence.getParametersSerialised()) > ttl) {
- inputHasCachedTime.remove(occurrence.getParametersSerialised());
- }
- if (inputHasCachedTime.containsKey(occurrence.getParametersSerialised())) {
- if (Configuration.getStaleness().equals("shrink")) {
- if (Objects.deepEquals(inputHasOutput.get(occurrence.getParametersSerialised()), occurrence.getReturnValue())) {
- realSavedTime += occurrence.getExecutionTime();
- } else {
- stales++;
- }
- }
- blindedSavedTime += occurrence.getExecutionTime();
- hits++;
- } else {
- inputHasCachedTime.put(occurrence.getParametersSerialised(), adjustedEndTime);
- if (Configuration.getStaleness().equals("shrink")) {
- inputHasOutput.put(occurrence.getParametersSerialised(), occurrence.getReturnValue());
- }
- computationTime += occurrence.getExecutionTime();
- timeInCache += ttl;
- }
+ private final Pareto pareto;
+
+ public Simulator() {
+ this.pareto = new Pareto();
+ }
+
+ public static void simulate(List<Occurrence> occurrences, Pareto pareto) {
+ Pareto computeIfAbsent = StorageManager.computeIfAbsent(occurrences, () -> {
+ if ("exhaustive".equals(Configuration.getKernel())) simulate(occurrences, generateAllTTLs(occurrences), pareto);
+ else if ("optimised".equals(Configuration.getKernel())) simulate(occurrences, generateTTLsOfInterest(occurrences), pareto);
+ else testKernels(occurrences);
+ return pareto;
+ });
+ computeIfAbsent.values().forEach(pareto::addIfPareto);
+ }
+
+ public static void simulate(List<Occurrence> occurrences, Stream<Long> ttls, Pareto pareto) {
+ ttls.forEach(actualTTL -> simulate(occurrences.stream(), actualTTL, pareto));
+ }
+
+ public static void simulate(Stream<Occurrence> occurrences, long ttl, Pareto pareto) {
+ Map<String, Long> inputHasCachedTime = new HashMap<>();
+ Map<String, Object> inputHasOutput = new HashMap<>();
+
+ long blindedSavedTime = 0;
+ long realSavedTime = 0;
+ long hits = 0;
+ long computationTime = 0;
+ long timeInCache = 0;
+ long stales = 0;
+
+ Iterator<Occurrence> iterator = occurrences.iterator();
+ while (iterator.hasNext()) {
+ Occurrence occurrence = iterator.next();
+ long adjustedStartTime = occurrence.getStartTime() - blindedSavedTime;
+ long adjustedEndTime = occurrence.getEndTime() - blindedSavedTime;
+
+ if (occurrence.getExecutionTime() < 0) throw new RuntimeException("executionTime cannot be under zero");
+ if (adjustedEndTime < adjustedStartTime) throw new RuntimeException("adjustedEndTime should not be lesser than adjustedStartTime");
+
+ if (inputHasCachedTime.containsKey(occurrence.getParametersSerialised()) &&
+ adjustedStartTime - inputHasCachedTime.get(occurrence.getParametersSerialised()) > ttl) {
+ inputHasCachedTime.remove(occurrence.getParametersSerialised());
+ }
+ if (inputHasCachedTime.containsKey(occurrence.getParametersSerialised())) {
+ if (Configuration.getStaleness().equals("shrink")) {
+ if (Objects.deepEquals(inputHasOutput.get(occurrence.getParametersSerialised()), occurrence.getReturnValue())) {
+ realSavedTime += occurrence.getExecutionTime();
+ } else {
+ stales++;
+ }
}
- Metrics metrics = new Metrics(ttl, hits, timeInCache, computationTime, stales, Configuration.getStaleness().equals("shrink") ? realSavedTime : blindedSavedTime);
- pareto.addIfPareto(metrics);
+ blindedSavedTime += occurrence.getExecutionTime();
+ hits++;
+ } else {
+ inputHasCachedTime.put(occurrence.getParametersSerialised(), adjustedEndTime);
+ if (Configuration.getStaleness().equals("shrink")) inputHasOutput.put(occurrence.getParametersSerialised(), occurrence.getReturnValue());
+ computationTime += occurrence.getExecutionTime();
+ timeInCache += ttl;
+ }
}
-
- public static Stream<Long> generateTTLsOfInterest(Stream<Occurrence> occurrences) {
- return generateTTLsOfInterest(occurrences.collect(Collectors.toList()));
+ Metrics metrics = new Metrics(ttl, hits, timeInCache, computationTime, stales, Configuration.getStaleness().equals("shrink") ? realSavedTime : blindedSavedTime);
+ pareto.addIfPareto(metrics);
+ }
+
+ public static Stream<Long> generateTTLsOfInterest(List<Occurrence> occurrences) {
+ List<Long> windows = new ArrayList<>();
+ for (int hits = 1; hits < occurrences.size(); hits++) {
+ long window = occurrences.get(hits).getStartTime() - occurrences.get(hits - 1).getEndTime();
+ if (window > 0) windows.add(window);
}
- public static Stream<Long> generateTTLsOfInterest(List<Occurrence> occurrences) {
- List<Long> windows = new ArrayList<>();
- for (int hits = 1; hits < occurrences.size(); hits++) {
- long window = occurrences.get(hits).getStartTime() - occurrences.get(hits - 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();
+ 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);
+ }
}
-
- 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;
- }
- }
- return LongStream.rangeClosed(minTTL, maxTTL).boxed().parallel();
+ 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;
}
-
- private static void testKernels(List<Occurrence> occurrences) {
- Pareto optimisedPareto = new Pareto();
- Pareto exhaustivePareto = new Pareto();
-
- Map<String, List<Occurrence>> inputHasOccurrences = Method.groupByInput(occurrences);
- Set<Long> ttlsOfInterest = inputHasOccurrences.values().stream()
- .map(Simulator::generateTTLsOfInterest)
- .reduce(Stream::concat)
- .orElse(Stream.empty())
- .collect(Collectors.toSet());
-
- simulate(occurrences, ttlsOfInterest.stream(), optimisedPareto);
- simulate(occurrences, generateAllTTLs(occurrences), exhaustivePareto);
-
- List<Long> missingTTLs = exhaustivePareto.values().stream().map(Metrics::getTtl)
- .filter(ttl -> !ttlsOfInterest.contains(ttl))
- .sorted()
- .collect(Collectors.toList());
- if (!missingTTLs.isEmpty()) {
- System.out.println("=== " + Configuration.getInput() + " ===");
- System.out.println("\tMissing ttls: " + missingTTLs);
- }
-
- Metrics maxExhaustiveMetrics = exhaustivePareto.getBestMetrics();
- Metrics maxOptimisedMetrics = optimisedPareto.getBestMetrics();
- if (maxExhaustiveMetrics.getTtl() != maxOptimisedMetrics.getTtl()) {
- System.out.println("=== " + Configuration.getInput() + " ===");
- System.out.println("\tDIFFERENT BEST METRICS");
- System.out.println("\tOptimised: " + maxOptimisedMetrics);
- System.out.println("\tExhaustive: " + maxExhaustiveMetrics);
- switch (maxExhaustiveMetrics.compareTo(maxOptimisedMetrics)) {
- case -1:
- System.out.println("\tOptimised won");
- break;
- case 1:
- System.out.println("\tExhaustive won");
- break;
- default:
- System.out.println("\tEquivalent recommendation");
- break;
- }
- }
+ return LongStream.rangeClosed(minTTL, maxTTL).boxed().parallel();
+ }
+
+ private static void testKernels(List<Occurrence> occurrences) {
+ Pareto optimisedPareto = new Pareto();
+ Pareto exhaustivePareto = new Pareto();
+
+ Map<String, List<Occurrence>> inputHasOccurrences = Method.groupByInput(occurrences);
+ Set<Long> ttlsOfInterest = inputHasOccurrences.values().stream()
+ .map(Simulator::generateTTLsOfInterest)
+ .reduce(Stream::concat)
+ .orElse(Stream.empty())
+ .collect(Collectors.toSet());
+
+ simulate(occurrences, ttlsOfInterest.stream(), optimisedPareto);
+ simulate(occurrences, generateAllTTLs(occurrences), exhaustivePareto);
+
+ List<Long> missingTTLs = exhaustivePareto.values().stream().map(Metrics::getTtl)
+ .filter(ttl -> !ttlsOfInterest.contains(ttl))
+ .sorted()
+ .collect(Collectors.toList());
+ if (!missingTTLs.isEmpty()) {
+ System.out.println("=== " + Configuration.getInput() + " ===");
+ System.out.println("\tMissing ttls: " + missingTTLs);
}
- public Pareto getPareto() {
- return pareto;
+ Metrics maxExhaustiveMetrics = exhaustivePareto.getBestMetrics();
+ Metrics maxOptimisedMetrics = optimisedPareto.getBestMetrics();
+ if (maxExhaustiveMetrics.getTtl() != maxOptimisedMetrics.getTtl()) {
+ System.out.println("=== " + Configuration.getInput() + " ===");
+ System.out.println("\tDIFFERENT BEST METRICS");
+ System.out.println("\tOptimised: " + maxOptimisedMetrics);
+ System.out.println("\tExhaustive: " + maxExhaustiveMetrics);
+ if (maxExhaustiveMetrics.compareTo(maxOptimisedMetrics) < 0) System.out.println("\tOptimised won");
+ else if (maxExhaustiveMetrics.compareTo(maxOptimisedMetrics) > 0) System.out.println("\tExhaustive won");
+ else System.out.println("\tEquivalent recommendation");
}
+ }
- public void simulate(List<Occurrence> occurrences) {
- simulate(occurrences, this.pareto);
- }
+ public Pareto getPareto() {
+ return pareto;
+ }
- public void simulate(Stream<Occurrence> occurrences, long ttl) {
- simulate(occurrences, ttl, this.pareto);
- }
+ public void simulate(List<Occurrence> occurrences) {
+ simulate(occurrences, this.pareto);
+ }
+
+ public void simulate(Stream<Occurrence> occurrences, long ttl) {
+ simulate(occurrences, ttl, this.pareto);
+ }
}
src/main/java/br/ufrgs/inf/prosoft/tfcache/TFCache.java 207(+94 -113)
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 19873f7..22238de 100755
--- a/src/main/java/br/ufrgs/inf/prosoft/tfcache/TFCache.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/tfcache/TFCache.java
@@ -1,8 +1,3 @@
-/*
- * 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.tfcache;
import br.ufrgs.inf.prosoft.tfcache.configuration.Configuration;
@@ -19,122 +14,108 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Stream;
-/**
- * @author romulo
- */
public class TFCache {
- private static final Logger LOGGER = Logger.getLogger(TFCache.class.getName());
- private final List<Method> methods;
+ private static final Logger LOGGER = Logger.getLogger(TFCache.class.getName());
+ private final List<Method> methods;
- public TFCache(List<Method> methods) {
- this.methods = methods;
- }
+ public TFCache(List<Method> methods) {
+ this.methods = methods;
+ }
- public Stream<Method> methods() {
- return this.methods.stream();
- }
+ public Stream<Method> methods() {
+ return this.methods.stream();
+ }
- 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());
- if (Configuration.getVerbose()) {
- this.methods.forEach(Method::recommendTTL);
- } else {
- this.methods.stream().parallel().forEach(Method::recommendTTL);
- }
- LOGGER.log(Level.INFO, "Removing not recommended from {0}", this.methods.size());
- this.methods.removeIf(method -> method.getBestMetrics().getSavedTime() == 0);
- LOGGER.log(Level.INFO, "Ranking {0} methods according saved time", this.methods.size());
- this.methods.sort((method1, method2) -> Double.compare(method2.getBestMetrics().getSavedTime(), method1.getBestMetrics().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.getBestMetrics().getTtl()
- + " Saves " + method.getBestMetrics().getSavedTime()
- + " Hits " + method.getBestMetrics().getHits()
- + " Computation " + method.getBestMetrics().getComputationTime()
- + " TimeInCache " + method.getBestMetrics().getTimeInCache()
- + " Stales " + method.getBestMetrics().getStales()));
+ 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());
+ if (Configuration.getVerbose()) this.methods.forEach(Method::recommendTTL);
+ else this.methods.stream().parallel().forEach(Method::recommendTTL);
+ LOGGER.log(Level.INFO, "Removing not recommended from {0}", this.methods.size());
+ this.methods.removeIf(method -> method.getBestMetrics().getSavedTime() == 0);
+ LOGGER.log(Level.INFO, "Ranking {0} methods according saved time", this.methods.size());
+ this.methods.sort((method1, method2) -> Double.compare(method2.getBestMetrics().getSavedTime(), method1.getBestMetrics().getSavedTime()));
+ LOGGER.log(Level.INFO, "Printing recommendations for {0} methods", this.methods.size());
+ this.methods.forEach(method -> System.out.println(method.getName()
+ + " Occurrences " + method.occurrences().count()
+ + " Inputs " + method.groupsOfOccurrences().count()
+ + " TTL " + method.getBestMetrics().getTtl()
+ + " Saves " + method.getBestMetrics().getSavedTime()
+ + " Hits " + method.getBestMetrics().getHits()
+ + " Computation " + method.getBestMetrics().getComputationTime()
+ + " TimeInCache " + method.getBestMetrics().getTimeInCache()
+ + " Stales " + method.getBestMetrics().getStales()));
+ }
- 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);
- }
- LOGGER.log(Level.INFO, "Removing not reusable inputs from {0} methods", this.methods.size());
- this.methods.forEach(Method::removeSingleOccurrences);
- 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());
- if (Configuration.getVerbose()) {
- this.methods.forEach(Method::recommendTTLPerInput);
- } else {
- this.methods.stream().parallel().forEach(Method::recommendTTLPerInput);
- }
- LOGGER.log(Level.INFO, "Removing not recommended inputs from {0}", this.methods.size());
- this.methods.forEach(Method::removeNotRecommendedInputs);
- 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) -> Double.compare(method2.getEstimatedSavedTime(), method1.getEstimatedSavedTime()));
- LOGGER.log(Level.INFO, "Printing recommendations for {0} methods", this.methods.size());
- this.methods.forEach(method -> {
- if (method.getBestMetrics() != null) {
- System.out.println(method.getName()
- + " Occurrences " + method.getOccurrencesSize()
- + " Inputs " + method.groupsOfOccurrences().count()
- + " TTL " + method.getBestMetrics().getTtl()
- + " Saves " + method.getBestMetrics().getSavedTime()
- + " Hits " + method.getBestMetrics().getHits()
- + " Computation " + method.getBestMetrics().getComputationTime()
- + " TimeInCache " + method.getBestMetrics().getTimeInCache()
- + " Stales " + method.getBestMetrics().getStales());
- } else {
- System.out.println(method.getName());
- }
- if (Configuration.getVerbose()) {
- method.groupsOfOccurrences().forEach(group -> System.out.println("\t" + group.getParameters().hashCode()
- + " Occurrences " + group.getOccurrencesSize()
- + " -> TTL " + group.getTtl()
- + " Saves " + group.getSavedTime()
- + " Hits " + group.getBestMetrics().getHits()
- + " Computation " + group.getBestMetrics().getComputationTime()
- + " TimeInCache " + group.getBestMetrics().getTimeInCache()
- + " Stales " + group.getBestMetrics().getHits()));
- }
- });
- try (FileWriter fileWriter = new FileWriter(Configuration.getOutput())) {
- JsonObject jsonCacheableParameters = new JsonObject();
- this.methods.forEach(method -> {
- JsonObject cacheableParameters = new JsonObject();
- method.groupsOfOccurrences().forEach(group -> cacheableParameters.addProperty(group.getParameters(), group.getTtl()));
- jsonCacheableParameters.add(method.getName(), cacheableParameters);
- });
- Gson gson = new GsonBuilder().setPrettyPrinting().create();
- gson.toJson(jsonCacheableParameters, fileWriter);
- } catch (IOException ex) {
- LOGGER.log(Level.SEVERE, "invalid <outputPath>");
- }
+ 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);
}
-
- public void recommend() {
- if (Configuration.getVerbose()) {
- Configuration.setInput(Arrays.stream(Configuration.getInput().split("/")).reduce((a, b) -> b).orElse(""));
- }
- if (Configuration.getLevel().equals("method")) {
- recommendCacheableMethods();
- } else {
- recommendCacheableInputs();
- }
+ LOGGER.log(Level.INFO, "Removing not reusable inputs from {0} methods", this.methods.size());
+ this.methods.forEach(Method::removeSingleOccurrences);
+ 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());
+ if (Configuration.getVerbose()) this.methods.forEach(Method::recommendTTLPerInput);
+ else this.methods.stream().parallel().forEach(Method::recommendTTLPerInput);
+ LOGGER.log(Level.INFO, "Removing not recommended inputs from {0}", this.methods.size());
+ this.methods.forEach(Method::removeNotRecommendedInputs);
+ 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) -> Double.compare(method2.getEstimatedSavedTime(), method1.getEstimatedSavedTime()));
+ LOGGER.log(Level.INFO, "Printing recommendations for {0} methods", this.methods.size());
+ this.methods.forEach(method -> {
+ if (method.getBestMetrics() != null) {
+ System.out.println(method.getName()
+ + " Occurrences " + method.occurrences().count()
+ + " Inputs " + method.groupsOfOccurrences().count()
+ + " TTL " + method.getBestMetrics().getTtl()
+ + " Saves " + method.getBestMetrics().getSavedTime()
+ + " Hits " + method.getBestMetrics().getHits()
+ + " Computation " + method.getBestMetrics().getComputationTime()
+ + " TimeInCache " + method.getBestMetrics().getTimeInCache()
+ + " Stales " + method.getBestMetrics().getStales());
+ } else {
+ System.out.println(method.getName());
+ }
+ if (Configuration.getVerbose()) {
+ method.groupsOfOccurrences().forEach(group -> System.out.println("\t" + group.getParameters().hashCode()
+ + " Occurrences " + group.occurrences().count()
+ + " -> TTL " + group.getBestMetrics().getTtl()
+ + " Saves " + group.getBestMetrics().getSavedTime()
+ + " Hits " + group.getBestMetrics().getHits()
+ + " Computation " + group.getBestMetrics().getComputationTime()
+ + " TimeInCache " + group.getBestMetrics().getTimeInCache()
+ + " Stales " + group.getBestMetrics().getHits()));
+ }
+ });
+ try (FileWriter fileWriter = new FileWriter(Configuration.getOutput())) {
+ JsonObject jsonCacheableParameters = new JsonObject();
+ this.methods.forEach(method -> {
+ JsonObject cacheableParameters = new JsonObject();
+ method.groupsOfOccurrences().forEach(it -> cacheableParameters.addProperty(it.getParameters(), it.getBestMetrics().getTtl()));
+ jsonCacheableParameters.add(method.getName(), cacheableParameters);
+ });
+ Gson gson = new GsonBuilder().setPrettyPrinting().create();
+ gson.toJson(jsonCacheableParameters, fileWriter);
+ } catch (IOException ex) {
+ LOGGER.log(Level.SEVERE, "invalid <outputPath>");
}
+ }
+
+ public void recommend() {
+ if (Configuration.getVerbose()) Configuration.setInput(Arrays.stream(Configuration.getInput().split("/")).reduce((a, b) -> b).orElse(""));
+ if (Configuration.getLevel().equals("method")) recommendCacheableMethods();
+ else recommendCacheableInputs();
+ }
}