aplcachetf
Changes
src/main/java/br/ufrgs/inf/prosoft/aplcachetf/extension/metadata/GroupOfOccurrences.java 131(+46 -85)
src/main/java/br/ufrgs/inf/prosoft/aplcachetf/extension/metrics/CacheabilityMetrics.java 26(+11 -15)
Details
diff --git a/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/adapter/TraceReader.java b/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/adapter/TraceReader.java
index d1f63d4..bb4d95a 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/adapter/TraceReader.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/adapter/TraceReader.java
@@ -12,6 +12,7 @@ import br.ufrgs.inf.prosoft.tfcache.metadata.OccurrenceReference;
import br.ufrgs.inf.prosoft.trace.Parameter;
import br.ufrgs.inf.prosoft.trace.Trace;
import br.ufrgs.inf.prosoft.trace.TraceReference;
+
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -21,7 +22,6 @@ import java.util.logging.Logger;
import java.util.stream.Collectors;
/**
- *
* @author romulo
*/
public class TraceReader extends br.ufrgs.inf.prosoft.trace.reader.TraceReader {
@@ -39,9 +39,7 @@ public class TraceReader extends br.ufrgs.inf.prosoft.trace.reader.TraceReader {
occurrence = new OccurrenceReference(traceReference.getIndex(), traceReference.getInstance(), trace.getStartTime(), trace.getEndTime(), trace.getUserSession());
} else {
occurrence = new OccurrenceConcrete(trace.getInstance(),
- trace.getParameters().stream()
- .map(Parameter::getData)
- .collect(Collectors.toList()).toArray(),
+ trace.getParameters().stream().map(Parameter::getData).toArray(),
trace.getReturn().getData(),
trace.getStartTime(),
trace.getEndTime(),
diff --git a/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/extension/APLCache.java b/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/extension/APLCache.java
index db01d6e..ca6ca94 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/extension/APLCache.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/extension/APLCache.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.aplcachetf.extension;
import br.ufrgs.inf.prosoft.aplcachetf.extension.metadata.Method;
@@ -11,122 +6,117 @@ import br.ufrgs.inf.prosoft.aplcachetf.extension.metrics.Thresholds;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
+
import java.io.FileWriter;
import java.io.IOException;
+import java.text.MessageFormat;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
-/**
- *
- * @author root
- */
public class APLCache {
- private static final Logger LOGGER = Logger.getLogger(APLCache.class.getName());
-
- private final List<Method> methods;
-
- public APLCache(List<Method> methods) {
- this.methods = methods;
- }
-
- private void calculateMetrics() {
- LOGGER.log(Level.INFO, "Calculating metrics for {0} methods...", this.methods.size());
- this.methods.stream().parallel().forEach(Method::calculateMetrics);
- }
-
- private void calculateThresholds(int kStdDev) {
- LOGGER.log(Level.INFO, "Calculating thresholds for {0} methods with {1} stdDev...", new Object[]{this.methods.size(), kStdDev});
-
- Thresholds.reset();
- Thresholds.population = getPopulation();
- this.methods.stream().forEach(Method::calculateThresholds);
-
- LOGGER.log(Level.INFO, "\tAverage ExecutionTime: {0}", Thresholds.getAverageExecutionTime());
- LOGGER.log(Level.INFO, "\tStdDv ExecutionTime: {0}", Thresholds.getStdDevExecutionTimeRatio());
- LOGGER.log(Level.INFO, "\tThreshold ExecutionTime: {0}", Thresholds.expensivenessThreshold(kStdDev));
- LOGGER.log(Level.INFO, "\tAverage HitRatio: {0}", Thresholds.getAverageHitRatio());
- LOGGER.log(Level.INFO, "\tStdDv HitRatio: {0}", Thresholds.getStdDevHitRatio());
- LOGGER.log(Level.INFO, "\tThreshold HitRatio: {0}", Thresholds.hitThreshold(kStdDev));
- LOGGER.log(Level.INFO, "\tAverage MissRatio: {0}", Thresholds.getAverageMissRatio());
- LOGGER.log(Level.INFO, "\tStdDv MissRatio: {0}", Thresholds.getStdDevMissRatio());
- LOGGER.log(Level.INFO, "\tThreshold MissRatio: {0}", Thresholds.missThreshold(kStdDev));
- LOGGER.log(Level.INFO, "\tAverage Shareability: {0}", Thresholds.getAverageShareability());
- LOGGER.log(Level.INFO, "\tStdDv Shareability: {0}", Thresholds.getStdDevShareability());
- LOGGER.log(Level.INFO, "\tThreshold Shareability: {0}", Thresholds.shareabilityThreshold(kStdDev));
- LOGGER.log(Level.INFO, "\tAverage SavedTimePerTimeInCache: {0}", Thresholds.getAverageSavedTimePerTimeInCache());
- LOGGER.log(Level.INFO, "\tStdDv SavedTimePerTimeInCache: {0}", Thresholds.getStdDevSavedTimePerTimeInCache());
- LOGGER.log(Level.INFO, "\tThreshold SavedTimePerTimeInCache: {0}", Thresholds.savedTimePerTimeInCacheThreshold(kStdDev));
- }
-
- private void filterCacheableInputs(int kStdDev) {
- LOGGER.log(Level.INFO, "Filtering inputs of {0} methods under {1} stdDev threshold...", new Object[]{this.methods.size(), kStdDev});
- CacheabilityMetrics.K_STANDARD_DEVIATION = kStdDev;
- this.methods.forEach(Method::filterCacheableInputs);
- this.methods.removeIf(method -> method.groupsOfOccurrences().count() == 0);
- }
-
- private void removeSingleOccurrences() {
- int initialMethodsSize = this.methods.size();
- 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() == 0);
- int removedMethods = initialMethodsSize - this.methods.size();
- if (removedMethods > 0) {
- LOGGER.log(Level.INFO, "Removed {0} of {1} not reusable methods", new Object[]{removedMethods, initialMethodsSize});
- }
- }
-
- public void recommend(String outputPath) {
- recommend(0, outputPath);
- }
-
- public void recommend(int kStdDev, String outputPath) {
- LOGGER.log(Level.INFO, "Recommending TTL per method for {0} methods", this.methods.size());
- removeSingleOccurrences();
- calculateMetrics();
- calculateThresholds(kStdDev);
- filterCacheableInputs(kStdDev);
-
- LOGGER.log(Level.INFO, "{0} cacheable methods detected", this.methods.size());
- this.methods.sort((method1, method2) -> method2.getEstimatedSavedTimePerTimeInCache().compareTo(method1.getEstimatedSavedTimePerTimeInCache()));
-
- this.methods.forEach(method -> {
- if (method.getBestMetrics() != null) {
- System.out.println(method.getName()
- + " Occurrences " + method.getOccurrencesSize()
- + " Inputs " + method.groupsOfOccurrences().count()
- + " TTL " + method.getBestMetrics().getTtl()
- + " STpTiC " + method.getBestMetrics().getSavedTimePerTimeInCache()
- + " Saves " + method.getBestMetrics().getSavedTime()
- + " Hits " + method.getBestMetrics().getHits()
- + " Stales " + method.getBestMetrics().getStales());
- } else {
- System.out.println(method.getName()
- + " Occurrences " + method.getOccurrencesSize()
- + " Inputs " + method.groupsOfOccurrences().count());
- }
- });
- try (FileWriter fileWriter = new FileWriter(outputPath)) {
- 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 static final Logger LOGGER = Logger.getLogger(APLCache.class.getName());
+
+ private final List<Method> methods;
+
+ public APLCache(List<Method> methods) {
+ this.methods = methods;
+ }
+
+ private void calculateMetrics() {
+ LOGGER.info(MessageFormat.format("Calculating metrics for {0} methods...", this.methods.size()));
+ this.methods.stream().parallel().forEach(Method::calculateMetrics);
+ }
+
+ private void calculateThresholds(int kStdDev) {
+ LOGGER.info(MessageFormat.format("Calculating thresholds for {0} methods with {1} stdDev...", this.methods.size(), kStdDev));
+
+ Thresholds.reset();
+ Thresholds.population = getPopulation();
+ this.methods.forEach(Method::calculateThresholds);
+
+ LOGGER.info(MessageFormat.format("\tAverage ExecutionTime: {0}", Thresholds.getAverageExecutionTime()));
+ LOGGER.info(MessageFormat.format("\tStdDv ExecutionTime: {0}", Thresholds.getStdDevExecutionTime()));
+ LOGGER.info(MessageFormat.format("\tThreshold ExecutionTime: {0}", Thresholds.expensivenessThreshold(kStdDev)));
+ LOGGER.info(MessageFormat.format("\tAverage HitRatio: {0}", Thresholds.getAverageHitRatio()));
+ LOGGER.info(MessageFormat.format("\tStdDv HitRatio: {0}", Thresholds.getStdDevHitRatio()));
+ LOGGER.info(MessageFormat.format("\tThreshold HitRatio: {0}", Thresholds.hitThreshold(kStdDev)));
+ LOGGER.info(MessageFormat.format("\tAverage MissRatio: {0}", Thresholds.getAverageMissRatio()));
+ LOGGER.info(MessageFormat.format("\tStdDv MissRatio: {0}", Thresholds.getStdDevMissRatio()));
+ LOGGER.info(MessageFormat.format("\tThreshold MissRatio: {0}", Thresholds.missThreshold(kStdDev)));
+ LOGGER.info(MessageFormat.format("\tAverage Shareability: {0}", Thresholds.getAverageShareability()));
+ LOGGER.info(MessageFormat.format("\tStdDv Shareability: {0}", Thresholds.getStdDevShareability()));
+ LOGGER.info(MessageFormat.format("\tThreshold Shareability: {0}", Thresholds.shareabilityThreshold(kStdDev)));
+ LOGGER.info(MessageFormat.format("\tAverage Distance: {0}", Thresholds.getAverageDistance()));
+ LOGGER.info(MessageFormat.format("\tStdDv Distance: {0}", Thresholds.getStdDevDistance()));
+ LOGGER.info(MessageFormat.format("\tThreshold Distance: {0}", Thresholds.distanceThreshold(kStdDev)));
+ }
+
+ private void filterCacheableInputs(int kStdDev) {
+ LOGGER.info(MessageFormat.format("Filtering inputs of {0} methods under {1} stdDev threshold...", this.methods.size(), kStdDev));
+ CacheabilityMetrics.K_STANDARD_DEVIATION = kStdDev;
+ this.methods.forEach(Method::filterCacheableInputs);
+ this.methods.removeIf(method -> method.groupsOfOccurrences().count() == 0);
+ }
+
+ private void removeSingleOccurrences() {
+ int initialMethodsSize = this.methods.size();
+ LOGGER.info(MessageFormat.format("Removing not reusable inputs from {0} methods", this.methods.size()));
+ this.methods.forEach(Method::removeSingleOccurrences);
+ LOGGER.info(MessageFormat.format("Removing not reusable methods from {0} methods", this.methods.size()));
+ this.methods.removeIf(method -> method.groupsOfOccurrences().count() == 0);
+ int removedMethods = initialMethodsSize - this.methods.size();
+ if (removedMethods > 0) LOGGER.info(MessageFormat.format("Removed {0} of {1} not reusable methods", removedMethods, initialMethodsSize));
+ }
+
+ public void recommend(String outputPath) {
+ recommend(0, outputPath);
+ }
+
+ public void recommend(int kStdDev, String outputPath) {
+ LOGGER.info(MessageFormat.format("Recommending TTL per method for {0} methods", this.methods.size()));
+ removeSingleOccurrences();
+ calculateMetrics();
+ calculateThresholds(kStdDev);
+ filterCacheableInputs(kStdDev);
+
+ LOGGER.info(MessageFormat.format("{0} cacheable methods detected", this.methods.size()));
+ this.methods.sort((method1, method2) -> Double.compare(method2.getEstimatedSavedTime(), method1.getEstimatedSavedTime()));
+
+ this.methods.forEach(method -> {
+ if (method.getBestTFMetrics() != null) {
+ System.out.println(method.getName()
+ + " Occurrences " + method.occurrences().count()
+ + " Inputs " + method.groupsOfOccurrences().count()
+ + " TTL " + method.getBestTFMetrics().getTtl()
+ + " Saves " + method.getBestTFMetrics().getSavedTime()
+ + " Hits " + method.getBestTFMetrics().getHits()
+ + " Computation " + method.getBestTFMetrics().getComputationTime()
+ + " TimeInCache " + method.getBestTFMetrics().getTimeInCache()
+ + " Stales " + method.getBestTFMetrics().getStales());
+ } else {
+ System.out.println(method.getName()
+ + " Occurrences " + method.occurrences().count()
+ + " Inputs " + method.groupsOfOccurrences().count());
+ }
+ });
+ try (FileWriter fileWriter = new FileWriter(outputPath)) {
+ JsonObject jsonCacheableParameters = new JsonObject();
+ this.methods.forEach(method -> {
+ JsonObject cacheableParameters = new JsonObject();
+ method.groupsOfOccurrences().forEach(group -> cacheableParameters.addProperty(group.getParameters(), group.getMetrics().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 long getPopulation() {
- return this.methods.stream().map(Method::getOccurrencesSize).reduce(Integer::sum).orElse(0);
- }
+ private long getPopulation() {
+ return this.methods.stream().map(it -> it.occurrences().count()).reduce(Long::sum).orElse(0L);
+ }
}
diff --git a/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/extension/metadata/GroupOfOccurrences.java b/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/extension/metadata/GroupOfOccurrences.java
index 575546c..8336b5d 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/extension/metadata/GroupOfOccurrences.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/extension/metadata/GroupOfOccurrences.java
@@ -1,110 +1,71 @@
-/*
- * 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.aplcachetf.extension.metadata;
import br.ufrgs.inf.prosoft.aplcachetf.extension.metrics.Metrics;
import br.ufrgs.inf.prosoft.aplcachetf.extension.metrics.Thresholds;
import br.ufrgs.inf.prosoft.tfcache.Simulator;
import br.ufrgs.inf.prosoft.tfcache.metadata.Occurrence;
-import java.math.BigDecimal;
+import org.apache.commons.lang3.builder.EqualsBuilder;
+
+import java.util.Comparator;
import java.util.List;
-import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Stream;
-import org.apache.commons.lang3.builder.EqualsBuilder;
-/**
- *
- * @author root
- */
public class GroupOfOccurrences {
- private static final Logger LOGGER = Logger.getLogger(GroupOfOccurrences.class.getName());
-
- private final String parameters;
- private final List<Occurrence> occurrences;
- private Metrics bestMetrics;
-
- public GroupOfOccurrences(String parameters, List<Occurrence> occurrences) {
- this.parameters = parameters;
- this.occurrences = occurrences;
- }
-
- public String getParameters() {
- return this.parameters;
- }
-
- public Stream<Occurrence> occurrences() {
- return this.occurrences.stream();
- }
-
- public int getOccurrencesSize() {
- return this.occurrences.size();
- }
-
- public Metrics getBestMetrics() {
- if (this.bestMetrics == null) {
- throw new RuntimeException("SavedTimePerTimeInCache must be calculated");
- }
- return this.bestMetrics;
- }
+ private static final Logger LOGGER = Logger.getLogger(GroupOfOccurrences.class.getName());
- public long getTtl() {
- return getBestMetrics().getTfmetrics().getTtl();
- }
+ private final String parameters;
+ private final List<Occurrence> occurrences;
+ private Metrics metrics;
- public long getHits() {
- return getBestMetrics().getTfmetrics().getHits();
- }
+ public GroupOfOccurrences(String parameters, List<Occurrence> occurrences) {
+ this.parameters = parameters;
+ this.occurrences = occurrences;
+ }
- public long getStales() {
- return getBestMetrics().getTfmetrics().getStales();
- }
+ public String getParameters() {
+ return this.parameters;
+ }
- public long getSavedTime() {
- return getBestMetrics().getTfmetrics().getSavedTime();
- }
+ public Stream<Occurrence> occurrences() {
+ return this.occurrences.stream();
+ }
- public BigDecimal getSavedTimePerTimeInCache() {
- return getBestMetrics().getTfmetrics().getSavedTimePerTimeInCache();
- }
+ public Metrics getMetrics() {
+ if (this.metrics == null) throw new RuntimeException("Metrics must be calculated");
+ return this.metrics;
+ }
- protected void calculateMetrics() {
- if (this.bestMetrics != null) {
- LOGGER.log(Level.WARNING, "Metrics already calculated");
- }
- if (this.occurrences.size() < 2) {
- throw new RuntimeException("Not reusable input");
- }
+ protected void calculateMetrics() {
+ if (this.metrics != null) LOGGER.warning("Metrics already calculated");
+ if (this.occurrences.size() < 2) throw new RuntimeException("Not reusable input");
- this.bestMetrics = new Metrics();
+ this.metrics = new Metrics();
- this.occurrences.sort((occurrence1, occurrence2) -> Long.compare(occurrence1.getStartTime(), occurrence2.getStartTime()));
- Simulator.simulate(this.occurrences, this.bestMetrics.getTfmetrics());
+ this.occurrences.sort(Comparator.comparingLong(Occurrence::getStartTime));
+ Simulator.simulate(this.occurrences, getMetrics().getPareto());
- for (int i = 0; i < this.occurrences.size(); i++) {
- Occurrence occurrence = this.occurrences.get(i);
- Object returnValue = occurrence.getReturnValue();
- for (int j = i + 1; j < this.occurrences.size(); j++) {
- Occurrence other = this.occurrences.get(j);
- if (EqualsBuilder.reflectionEquals(returnValue, other.getReturnValue())) {
- this.bestMetrics.addSameOccurrence(occurrence);
- continue;
- }
- this.bestMetrics.addDifferentReturnOccurrence();
- }
+ for (int i = 0; i < this.occurrences.size(); i++) {
+ Occurrence occurrence = this.occurrences.get(i);
+ Object returnValue = occurrence.getReturnValue();
+ for (int j = i + 1; j < this.occurrences.size(); j++) {
+ Occurrence other = this.occurrences.get(j);
+ if (EqualsBuilder.reflectionEquals(returnValue, other.getReturnValue())) {
+ getMetrics().registerReuse(occurrence);
+ } else {
+ getMetrics().registerChange();
}
+ }
}
-
- protected void calculateThresholds() {
- Thresholds.executionTimes.add(this.bestMetrics.getSameOccurrencesTotalExecutionTime());
- Thresholds.hitRatios.add(this.bestMetrics.getHitRatio());
- Thresholds.missRatios.add(this.bestMetrics.getMissRatio());
- Thresholds.shareabilities.add(this.bestMetrics.getShareability());
- Thresholds.savedTimePerTimeInCache.add(this.bestMetrics.getTfmetrics().getSavedTimePerTimeInCache());
- }
+ }
+
+ protected void calculateThresholds() {
+ Thresholds.EXECUTION_TIMES.add(getMetrics().getReusableExecutionTime());
+ Thresholds.HIT_RATIOS.add(getMetrics().getHitRatio());
+ Thresholds.MISS_RATIOS.add(getMetrics().getMissRatio());
+ Thresholds.SHAREABILITIES.add(getMetrics().getShareability());
+ Thresholds.DISTANCES.add(getMetrics().getMinEuclideanDistance());
+ }
}
diff --git a/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/extension/metadata/Method.java b/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/extension/metadata/Method.java
index cf32a1f..abd39a5 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/extension/metadata/Method.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/extension/metadata/Method.java
@@ -7,22 +7,21 @@ package br.ufrgs.inf.prosoft.aplcachetf.extension.metadata;
import br.ufrgs.inf.prosoft.aplcachetf.extension.metrics.CacheabilityPatternDecider;
import br.ufrgs.inf.prosoft.tfcache.Metrics;
+import br.ufrgs.inf.prosoft.tfcache.Pareto;
import br.ufrgs.inf.prosoft.tfcache.StorageManager;
import br.ufrgs.inf.prosoft.tfcache.configuration.Configuration;
import br.ufrgs.inf.prosoft.tfcache.metadata.Occurrence;
-import java.math.BigDecimal;
+
+import java.text.MessageFormat;
import java.util.ArrayList;
-import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
-import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
- *
* @author root
*/
public class Method {
@@ -30,18 +29,14 @@ public class Method {
private static final Logger LOGGER = Logger.getLogger(Method.class.getName());
private final String name;
- private List<Occurrence> occurrences;
+ private final List<Occurrence> occurrences;
private List<GroupOfOccurrences> groupsOfOccurrences;
- private Metrics bestMetrics;
+ private Metrics bestTFMetrics;
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");
- }
+ if (occurrences == null) throw new RuntimeException("Occurrences is null");
+ if (occurrences.isEmpty()) throw new RuntimeException("Occurrences is empty");
this.occurrences = occurrences;
}
@@ -49,23 +44,14 @@ public class Method {
return this.name;
}
- public Metrics getBestMetrics() {
- return this.bestMetrics;
+ public Metrics getBestTFMetrics() {
+ if (this.bestTFMetrics == null) throw new RuntimeException("trying to access metrics before calculating it");
+ return this.bestTFMetrics;
}
- public long getEstimatedSavedTime() {
- if (getBestMetrics() != null) {
- return getBestMetrics().getSavedTime();
- }
- return groupsOfOccurrences().map(group -> group.getSavedTime()).reduce(Long::sum).orElse(0L);
- }
-
- public BigDecimal getEstimatedSavedTimePerTimeInCache() {
- if (getBestMetrics() != null) {
- return getBestMetrics().getSavedTimePerTimeInCache();
- }
- GroupOfOccurrences max = groupsOfOccurrences().max(Comparator.comparing(GroupOfOccurrences::getSavedTimePerTimeInCache)).get();
- return max.getSavedTimePerTimeInCache();
+ public double getEstimatedSavedTime() {
+ if (getBestTFMetrics() != null) return getBestTFMetrics().getSavedTime();
+ return groupsOfOccurrences().map(it -> it.getMetrics().getSavedTime()).reduce(Double::sum).orElse(0D);
}
public Stream<Occurrence> occurrences() {
@@ -73,24 +59,16 @@ public class Method {
}
public Stream<GroupOfOccurrences> groupsOfOccurrences() {
- if (this.groupsOfOccurrences == null) {
- groupByInput();
- }
+ if (this.groupsOfOccurrences == null) groupByInput();
return this.groupsOfOccurrences.stream();
}
- public int getOccurrencesSize() {
- return this.occurrences.size();
- }
-
private void groupByInput() {
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<>();
- }
+ if (oldValue == null) oldValue = new ArrayList<>();
oldValue.add(occurrence);
return oldValue;
});
@@ -101,46 +79,34 @@ public class Method {
}
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});
- }
+ if (this.groupsOfOccurrences == null) groupByInput();
+ int initialCountOfOccurrences = this.groupsOfOccurrences.size();
+ this.groupsOfOccurrences.removeIf(groupOfOccurrences -> groupOfOccurrences.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 void calculateMetrics() {
- if (this.groupsOfOccurrences == null) {
- groupByInput();
- }
+ if (this.groupsOfOccurrences == null) groupByInput();
groupsOfOccurrences().forEach(GroupOfOccurrences::calculateMetrics);
String uuid = Configuration.getUUID().replace("level:input", "level:method");
- Metrics metrics = StorageManager.get(uuid, this.occurrences);
- if (this.bestMetrics == null && metrics != null) {
- this.bestMetrics = metrics;
- }
+ Pareto pareto = StorageManager.get(uuid, this.occurrences);
+ if (pareto != null) this.bestTFMetrics = pareto.getBestMetrics();
}
public void calculateThresholds() {
- this.groupsOfOccurrences.stream().forEach(GroupOfOccurrences::calculateThresholds);
+ this.groupsOfOccurrences.forEach(GroupOfOccurrences::calculateThresholds);
}
public void filterCacheableInputs() {
int initialInputsSize = this.groupsOfOccurrences.size();
this.groupsOfOccurrences.removeIf(CacheabilityPatternDecider::isNotCacheable);
int removedInputs = initialInputsSize - this.groupsOfOccurrences.size();
- if (removedInputs > 0) {
- LOGGER.log(Level.INFO, "\tRemoved {0} of {1} uncacheable inputs from method {2}", new Object[]{removedInputs, initialInputsSize, this.name});
- }
+ if (removedInputs > 0) LOGGER.info(MessageFormat.format("\tRemoved {0} of {1} unreachable inputs from method {2}", removedInputs, initialInputsSize, this.name));
initialInputsSize = this.groupsOfOccurrences.size();
- this.groupsOfOccurrences.removeIf(groupOfOccurrence -> groupOfOccurrence.getTtl() == 0);
+ this.groupsOfOccurrences.removeIf(groupOfOccurrence -> groupOfOccurrence.getMetrics().getTtl() == 0);
removedInputs = initialInputsSize - this.groupsOfOccurrences.size();
- if (removedInputs > 0) {
- LOGGER.log(Level.INFO, "\tRemoved {0} of {1} inputs with 0 TTL from method {2}", new Object[]{removedInputs, initialInputsSize, this.name});
- }
+ if (removedInputs > 0) LOGGER.info(MessageFormat.format("\tRemoved {0} of {1} inputs with 0 TTL from method {2}", removedInputs, initialInputsSize, this.name));
}
@Override
diff --git a/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/extension/metrics/CacheabilityMetrics.java b/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/extension/metrics/CacheabilityMetrics.java
index cdd857c..9e74b48 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/extension/metrics/CacheabilityMetrics.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/extension/metrics/CacheabilityMetrics.java
@@ -7,37 +7,33 @@ public class CacheabilityMetrics {
public static int K_STANDARD_DEVIATION = 0;
public static boolean isStaticData(GroupOfOccurrences groupOfOccurrences) {
- if (groupOfOccurrences.getBestMetrics().getTfmetrics().getSavedTimePerTimeInCache().compareTo(Thresholds.savedTimePerTimeInCacheThreshold(K_STANDARD_DEVIATION)) < 0) {
- return false;
- }
- return groupOfOccurrences.getBestMetrics().getHitRatio() == 100.0;
+ if (groupOfOccurrences.getMetrics().getMinEuclideanDistance() > Thresholds.distanceThreshold(K_STANDARD_DEVIATION)) return false;
+ return groupOfOccurrences.getMetrics().getHitRatio() == 100.0;
}
public static boolean isNotStaticData(GroupOfOccurrences groupOfOccurrences) {
return !isStaticData(groupOfOccurrences);
}
- public static boolean changeMoreThanUsed(GroupOfOccurrences groupOfOccurrences) {
- return groupOfOccurrences.getBestMetrics().getMissRatio() > Thresholds.missThreshold(K_STANDARD_DEVIATION);
+ public static boolean isChangeable(GroupOfOccurrences groupOfOccurrences) {
+ return groupOfOccurrences.getMetrics().getMissRatio() > Thresholds.missThreshold(K_STANDARD_DEVIATION);
}
- public static boolean hasHighUsagePerCaching(GroupOfOccurrences groupOfOccurrences) {
- return groupOfOccurrences.getBestMetrics().getTfmetrics().getSavedTimePerTimeInCache().compareTo(Thresholds.savedTimePerTimeInCacheThreshold(K_STANDARD_DEVIATION)) >= 0;
+ public static boolean hasHighSavedTimeAndLowIdleTime(GroupOfOccurrences groupOfOccurrences) {
+ return groupOfOccurrences.getMetrics().getMinEuclideanDistance() <= Thresholds.distanceThreshold(K_STANDARD_DEVIATION);
}
- public static boolean hasLowUsagePerCaching(GroupOfOccurrences groupOfOccurrences) {
- return !hasHighUsagePerCaching(groupOfOccurrences);
+ public static boolean hasLowSavedTimeAndHighIdleTime(GroupOfOccurrences groupOfOccurrences) {
+ return !hasHighSavedTimeAndLowIdleTime(groupOfOccurrences);
}
public static boolean isUserSpecific(GroupOfOccurrences groupOfOccurrences) {
- if (groupOfOccurrences.getBestMetrics().getAmountOfIdentifiedSameOccurences() == 0) {
- return false;
- }
- return groupOfOccurrences.getBestMetrics().getShareability() < Thresholds.shareabilityThreshold(K_STANDARD_DEVIATION);
+ if (groupOfOccurrences.getMetrics().getShareableReuses() == 0) return false;
+ return groupOfOccurrences.getMetrics().getShareability() < Thresholds.shareabilityThreshold(K_STANDARD_DEVIATION);
}
public static boolean isExpensive(GroupOfOccurrences groupOfOccurrences) {
- return groupOfOccurrences.getBestMetrics().getSameOccurrencesAverageExecutionTime() >= Thresholds.expensivenessThreshold(K_STANDARD_DEVIATION);
+ return groupOfOccurrences.getMetrics().getAverageReusableExecutionTime() >= Thresholds.expensivenessThreshold(K_STANDARD_DEVIATION);
}
public static boolean isCheap(GroupOfOccurrences groupOfOccurrences) {
diff --git a/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/extension/metrics/CacheabilityPatternDecider.java b/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/extension/metrics/CacheabilityPatternDecider.java
index 72d97f8..babf47b 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/extension/metrics/CacheabilityPatternDecider.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/extension/metrics/CacheabilityPatternDecider.java
@@ -4,34 +4,16 @@ import br.ufrgs.inf.prosoft.aplcachetf.extension.metadata.GroupOfOccurrences;
public class CacheabilityPatternDecider {
- /**
- * Flowchart definition
- *
- * @param groupOfOccurrences
- * @return
- */
- public static boolean isCacheable(GroupOfOccurrences groupOfOccurrences) {
- boolean isStaticData = CacheabilityMetrics.isStaticData(groupOfOccurrences);
- if (isStaticData) {
- return true;
- }
- boolean changeMoreThanUsed = CacheabilityMetrics.changeMoreThanUsed(groupOfOccurrences);
- if (changeMoreThanUsed) {
- return false;
- }
- boolean hasHighUsagePerCaching = CacheabilityMetrics.hasHighUsagePerCaching(groupOfOccurrences);
- if (!hasHighUsagePerCaching) {
- return false;
- }
- boolean isUserSpecific = CacheabilityMetrics.isUserSpecific(groupOfOccurrences);
- if (isUserSpecific) {
- return true;
- }
- return CacheabilityMetrics.isExpensive(groupOfOccurrences);
- }
+ public static boolean isCacheable(GroupOfOccurrences groupOfOccurrences) {
+ if (CacheabilityMetrics.isStaticData(groupOfOccurrences)) return true;
+ if (CacheabilityMetrics.isChangeable(groupOfOccurrences)) return false;
+ if (CacheabilityMetrics.hasLowSavedTimeAndHighIdleTime(groupOfOccurrences)) return false;
+ if (CacheabilityMetrics.isUserSpecific(groupOfOccurrences)) return true;
+ return CacheabilityMetrics.isExpensive(groupOfOccurrences);
+ }
- public static boolean isNotCacheable(GroupOfOccurrences groupOfOccurrences) {
- return !isCacheable(groupOfOccurrences);
- }
+ public static boolean isNotCacheable(GroupOfOccurrences groupOfOccurrences) {
+ return !isCacheable(groupOfOccurrences);
+ }
}
diff --git a/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/extension/metrics/Metrics.java b/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/extension/metrics/Metrics.java
index 1e17c21..fd25e16 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/extension/metrics/Metrics.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/extension/metrics/Metrics.java
@@ -1,133 +1,123 @@
-/*
- * 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.aplcachetf.extension.metrics;
+import br.ufrgs.inf.prosoft.tfcache.Pareto;
import br.ufrgs.inf.prosoft.tfcache.metadata.Occurrence;
+
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashSet;
import java.util.Set;
-/**
- *
- * @author root
- */
public class Metrics {
-//exactly same method calls
-
- private final br.ufrgs.inf.prosoft.tfcache.Metrics tfmetrics;
- private long sameOccurrences;
-
- //number of same method calls with different return
- private long differentReturnOccurrences;
- private long sameOccurrencesExecutionTime;
-
- private long amountOfIdentifiedSameOccurences;
- private final Set<String> uniqueUsers;
-
- public Metrics() {
- sameOccurrences = 0L;
- differentReturnOccurrences = 0L;
- sameOccurrencesExecutionTime = 0L;
- amountOfIdentifiedSameOccurences = 0L;
- uniqueUsers = new HashSet<>();
- this.tfmetrics = new br.ufrgs.inf.prosoft.tfcache.Metrics();
- }
-
- public br.ufrgs.inf.prosoft.tfcache.Metrics getTfmetrics() {
- return tfmetrics;
- }
-
- public void addSameOccurrence(Occurrence occurrence) {
- sameOccurrences++;
- addSameOccurrencesTotalExecutionTime(occurrence.getExecutionTime());
-
- if (occurrence.getUserId() != null && !occurrence.getUserId().equals("Anonymous")) {
- uniqueUsers.add(occurrence.getUserId());
- addIdentifiedSameOccurence();
- }
- }
-
- public void addDifferentReturnOccurrence() {
- differentReturnOccurrences++;
- }
-
- private void addSameOccurrencesTotalExecutionTime(Long executionTime) {
- sameOccurrencesExecutionTime += executionTime;
- }
-
- private void addIdentifiedSameOccurence() {
- amountOfIdentifiedSameOccurences++;
- }
-
- public long getSameOccurrencesTotalExecutionTime() {
- return sameOccurrencesExecutionTime;
- }
-
- public double getSameOccurrencesAverageExecutionTime() {
- if (sameOccurrences == 0) {
- return 0;
- }
- return new BigDecimal(getSameOccurrencesTotalExecutionTime())
- .divide(new BigDecimal(sameOccurrences), 5, RoundingMode.HALF_UP)
- .doubleValue();
- }
-
- public Long getNumberOfOccurrences() {
- return sameOccurrences + differentReturnOccurrences;
- }
-
- public Long getNumberOfSameOccurrences() {
- return sameOccurrences;
- }
-
- public Long getNumberOfDifferentReturnOccurrences() {
- return differentReturnOccurrences;
- }
-
- //from 0% to 100%
- public double getHitRatio() {
- BigDecimal bd = new BigDecimal(getNumberOfSameOccurrences() * 100);
- return bd.divide(new BigDecimal(getNumberOfOccurrences()), 5, RoundingMode.HALF_UP).doubleValue();
- }
-
- //from 0% to 100%
- public double getMissRatio() {
- BigDecimal bd = new BigDecimal(getNumberOfDifferentReturnOccurrences() * 100);
- return bd.divide(new BigDecimal(getNumberOfOccurrences()), 5, RoundingMode.HALF_UP).doubleValue();
- }
-
- public double getShareability() {
- Long amountOfIdentifiedSameOccurences = getAmountOfIdentifiedSameOccurences();
- if (amountOfIdentifiedSameOccurences == 0) {
- return 100;
- }
- BigDecimal bd = new BigDecimal(getAmountOfUniqueIdentifiedSameOccurences() * 100);
- return bd.divide(new BigDecimal(amountOfIdentifiedSameOccurences), 5, RoundingMode.HALF_UP).doubleValue();
- }
-
- public Long getAmountOfIdentifiedSameOccurences() {
- return amountOfIdentifiedSameOccurences;
- }
- public int getAmountOfUniqueIdentifiedSameOccurences() {
- return uniqueUsers.size();
- }
-
- public Long getAmountOfAnonymousSameOccurences() {
- return sameOccurrences - amountOfIdentifiedSameOccurences;
- }
-
- @Override
- public String toString() {
- return "{"
- + "\"hitRatio\":" + getHitRatio() + ","
- + "\"missRatio\":" + getMissRatio() + ","
- + "\"shareability\":" + getShareability()
- + "}";
- }
+ private final Set<String> users;
+ private final Pareto pareto;
+ private long changeable;
+ private long reuses;
+ private long shareableReuses;
+ private long reusableExecutionTime;
+ private Double minEuclideanDistance;
+
+ public Metrics() {
+ users = new HashSet<>();
+ changeable = 0L;
+ reuses = 0L;
+ shareableReuses = 0L;
+ reusableExecutionTime = 0L;
+ pareto = new Pareto();
+ }
+
+ public void registerReuse(Occurrence occurrence) {
+ reuses++;
+ reusableExecutionTime += occurrence.getExecutionTime();
+ if (occurrence.getUserId() != null && !occurrence.getUserId().equals("Anonymous")) {
+ users.add(occurrence.getUserId());
+ shareableReuses++;
+ }
+ }
+
+ public void registerChange() {
+ changeable++;
+ }
+
+ public Pareto getPareto() {
+ return pareto;
+ }
+
+ public long getTtl() {
+ return getPareto().getBestMetrics().getTtl();
+ }
+
+ public double getSavedTime() {
+ return getPareto().getBestMetrics().getSavedTime();
+ }
+
+ public double getMinEuclideanDistance() {
+ if (minEuclideanDistance == null) minEuclideanDistance = getPareto().getNormalised().getMinEuclideanDistance();
+ return minEuclideanDistance;
+ }
+
+ public long getReusableExecutionTime() {
+ return reusableExecutionTime;
+ }
+
+ public double getAverageReusableExecutionTime() {
+ if (reuses == 0) return 0;
+ return new BigDecimal(getReusableExecutionTime())
+ .divide(new BigDecimal(reuses), 5, RoundingMode.HALF_UP)
+ .doubleValue();
+ }
+
+ public long getComparisons() {
+ return reuses + changeable;
+ }
+
+ public long getReuses() {
+ return reuses;
+ }
+
+ public long getChanges() {
+ return changeable;
+ }
+
+ public double getHitRatio() {
+ BigDecimal bd = new BigDecimal(getReuses() * 100);
+ return bd.divide(new BigDecimal(getComparisons()), 5, RoundingMode.HALF_UP).doubleValue();
+ }
+
+ public double getMissRatio() {
+ BigDecimal bd = new BigDecimal(getChanges() * 100);
+ return bd.divide(new BigDecimal(getComparisons()), 5, RoundingMode.HALF_UP).doubleValue();
+ }
+
+ public double getShareability() {
+ long shareableReuses = getShareableReuses();
+ if (shareableReuses == 0) {
+ return 100;
+ }
+ BigDecimal bd = new BigDecimal(getUsers() * 100);
+ return bd.divide(new BigDecimal(shareableReuses), 5, RoundingMode.HALF_UP).doubleValue();
+ }
+
+ public long getShareableReuses() {
+ return shareableReuses;
+ }
+
+ public int getUsers() {
+ return users.size();
+ }
+
+ public long getAnonymousReuses() {
+ return reuses - shareableReuses;
+ }
+
+ @Override
+ public String toString() {
+ return "{"
+ + "\"hitRatio\":" + getHitRatio() + ","
+ + "\"missRatio\":" + getMissRatio() + ","
+ + "\"shareability\":" + getShareability()
+ + "}";
+ }
}
diff --git a/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/extension/metrics/Thresholds.java b/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/extension/metrics/Thresholds.java
index 03eeca8..d5e7e6f 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/extension/metrics/Thresholds.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/extension/metrics/Thresholds.java
@@ -1,209 +1,150 @@
-/*
- * 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.aplcachetf.extension.metrics;
import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.math.MathContext;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
-/**
- *
- * @author romulo
- */
public class Thresholds {
- public static BigDecimal averageSavedTimePerTimeInCache;
-
- public static Double stdDevHitRatio;
- public static Double stdDevMissRatio;
- public static Double stdDevExecutionTimeRatio;
- public static BigDecimal stdDevSavedTimePerTimeInCache;
- public static Double stdDevShareability;
-
- public static long population;
-
- public static final List<Double> hitRatios = new ArrayList<>();
- public static final List<Double> missRatios = new ArrayList<>();
- public static final List<Long> executionTimes = new ArrayList<>();
- public static final List<Double> shareabilities = new ArrayList<>();
- public static final List<BigDecimal> savedTimePerTimeInCache = new ArrayList<>();
-
- public static void reset() {
- Thresholds.averageSavedTimePerTimeInCache = null;
-
- Thresholds.stdDevHitRatio = null;
- Thresholds.stdDevMissRatio = null;
- Thresholds.stdDevExecutionTimeRatio = null;
- Thresholds.stdDevSavedTimePerTimeInCache = null;
- Thresholds.stdDevShareability = null;
-
- Thresholds.population = 0;
-
- Thresholds.hitRatios.clear();
- Thresholds.missRatios.clear();
- Thresholds.executionTimes.clear();
- Thresholds.shareabilities.clear();
- Thresholds.savedTimePerTimeInCache.clear();
- }
-
- /**
- * General mean hit ratio of all calls
- *
- * @return
- */
- public static double getAverageHitRatio() {
- if (population == 0) {
- return 0;
- }
- return new BigDecimal(hitRatios.stream().reduce(Double::sum).orElse(0D)).divide(new BigDecimal(population), 5, RoundingMode.HALF_UP).doubleValue();
- }
-
- public static double getAverageMissRatio() {
- if (population == 0) {
- return 0;
- }
- return new BigDecimal(missRatios.stream().reduce(Double::sum).orElse(0D)).divide(new BigDecimal(population), 5, RoundingMode.HALF_UP).doubleValue();
- }
-
- public static double getAverageExecutionTime() {
- if (population == 0) {
- return 0;
- }
- return new BigDecimal(executionTimes.stream().reduce(Long::sum).orElse(0L)).divide(new BigDecimal(population), 5, RoundingMode.HALF_UP).doubleValue();
- }
-
- public static double getAverageShareability() {
- if (population == 0) {
- return 0;
- }
- return new BigDecimal(shareabilities.stream().reduce(Double::sum).orElse(0D)).divide(new BigDecimal(population), 5, RoundingMode.HALF_UP).doubleValue();
- }
-
- public static double getStdDevHitRatio() {
- if (population == 0) {
- return 0;
- }
- if (stdDevHitRatio != null) {
- return stdDevHitRatio;
- }
-
- double mean = getAverageHitRatio();
- double temp = hitRatios.stream()
- .map(hitRate -> (hitRate - mean) * (hitRate - mean))
- .reduce(Double::sum)
- .orElse(0D);
- stdDevHitRatio = Math.sqrt(temp / population);
- return stdDevHitRatio;
- }
-
- public static double getStdDevMissRatio() {
- if (population == 0) {
- return 0;
- }
- if (stdDevMissRatio != null) {
- return stdDevMissRatio;
- }
-
- double mean = getAverageMissRatio();
- double temp = missRatios.stream().map(missRatio -> (missRatio - mean) * (missRatio - mean))
- .reduce(Double::sum)
- .orElse(0D);
- stdDevMissRatio = Math.sqrt(temp / population);
- return stdDevMissRatio;
- }
-
- public static double getStdDevExecutionTimeRatio() {
- if (population == 0) {
- return 0;
- }
- if (stdDevExecutionTimeRatio != null) {
- return stdDevExecutionTimeRatio;
- }
-
- double mean = getAverageExecutionTime();
- double temp = executionTimes.stream()
- .map(executionTime -> (executionTime - mean) * (executionTime - mean))
- .reduce(Double::sum)
- .orElse(0D);
- stdDevExecutionTimeRatio = Math.sqrt(temp / population);
- return stdDevExecutionTimeRatio;
- }
-
- public static BigDecimal getStdDevSavedTimePerTimeInCache() {
- if (population == 0) {
- return new BigDecimal(BigInteger.ZERO);
- }
- if (stdDevSavedTimePerTimeInCache != null) {
- return stdDevSavedTimePerTimeInCache;
- }
-
- BigDecimal mean = getAverageSavedTimePerTimeInCache();
- BigDecimal temp = savedTimePerTimeInCache.stream()
- .map(frequency -> frequency.subtract(mean).multiply(frequency.subtract(mean)))
- .reduce(BigDecimal::add)
- .orElse(new BigDecimal(BigInteger.ZERO));
- stdDevSavedTimePerTimeInCache = temp.divide(new BigDecimal(population), MathContext.DECIMAL128).sqrt(MathContext.DECIMAL128);
- return stdDevSavedTimePerTimeInCache;
- }
-
- public static double getStdDevShareability() {
- if (population == 0) {
- return 0;
- }
- if (stdDevShareability != null) {
- return stdDevShareability;
- }
-
- double mean = getAverageShareability();
- double temp = shareabilities.stream()
- .map(shareability -> (shareability - mean) * (shareability - mean))
- .reduce(Double::sum)
- .orElse(0D);
- stdDevShareability = Math.sqrt(temp / population);
- return stdDevShareability;
- }
-
- public static BigDecimal getAverageSavedTimePerTimeInCache() {
- if (savedTimePerTimeInCache.isEmpty()) {
- return new BigDecimal(BigInteger.ZERO);
- }
- if (averageSavedTimePerTimeInCache != null) {
- return averageSavedTimePerTimeInCache;
- }
-
- averageSavedTimePerTimeInCache = savedTimePerTimeInCache.stream().reduce(BigDecimal::add).orElse(new BigDecimal(BigInteger.ZERO))
- .divide(new BigDecimal(savedTimePerTimeInCache.size()), MathContext.DECIMAL128);
- return averageSavedTimePerTimeInCache;
- }
-
-//getting X% with most hits
- public static double hitThreshold(int kStdDev) {
- return getAverageHitRatio() + (kStdDev * getStdDevHitRatio());
- }
-
-//getting X% with most misses
- public static double missThreshold(int kStdDev) {
- return getAverageMissRatio() + (kStdDev * getStdDevMissRatio());
- }
-
-//getting X% most expensive methods
- public static double expensivenessThreshold(int kStdDev) {
- return getAverageExecutionTime() + (kStdDev * getStdDevExecutionTimeRatio());
- }
-
- public static double shareabilityThreshold(int kStdDev) {
- return getAverageShareability() + (kStdDev * getStdDevShareability());
- }
-
-//getting X% most frenquent
- public static BigDecimal savedTimePerTimeInCacheThreshold(int kStdDev) {
- return getAverageSavedTimePerTimeInCache().add(getStdDevSavedTimePerTimeInCache().multiply(new BigDecimal(kStdDev)));
- }
+ public static final List<Double> DISTANCES = new ArrayList<>();
+ public static final List<Double> HIT_RATIOS = new ArrayList<>();
+ public static final List<Double> MISS_RATIOS = new ArrayList<>();
+ public static final List<Long> EXECUTION_TIMES = new ArrayList<>();
+ public static final List<Double> SHAREABILITIES = new ArrayList<>();
+ public static long population;
+ private static Double stdDevDistance;
+ private static Double stdDevHitRatio;
+ private static Double stdDevMissRatio;
+ private static Double stdDevExecutionTime;
+ private static Double stdDevShareability;
+
+
+ public static void reset() {
+ Thresholds.population = 0;
+
+ Thresholds.DISTANCES.clear();
+ Thresholds.stdDevDistance = null;
+
+ Thresholds.HIT_RATIOS.clear();
+ Thresholds.stdDevHitRatio = null;
+
+ Thresholds.MISS_RATIOS.clear();
+ Thresholds.stdDevMissRatio = null;
+
+ Thresholds.EXECUTION_TIMES.clear();
+ Thresholds.stdDevExecutionTime = null;
+
+ Thresholds.SHAREABILITIES.clear();
+ Thresholds.stdDevShareability = null;
+ }
+
+ public static double getAverageDistance() {
+ if (DISTANCES.isEmpty()) return 0D;
+ return DISTANCES.stream().reduce(Double::sum).orElse(0D) / DISTANCES.size();
+ }
+
+ public static double getStdDevDistance() {
+ if (population == 0) return 0;
+ if (stdDevDistance != null) return stdDevDistance;
+ double mean = getAverageDistance();
+ double temp = DISTANCES.stream()
+ .map(difference -> (difference - mean) * (difference - mean))
+ .reduce(Double::sum)
+ .orElse(0D);
+ stdDevDistance = Math.sqrt(temp / population);
+ return stdDevDistance;
+ }
+
+ public static double distanceThreshold(int kStdDev) {
+ return getAverageDistance() - (kStdDev * getStdDevDistance());
+ }
+
+
+ public static double getAverageHitRatio() {
+ if (population == 0) return 0;
+ return HIT_RATIOS.stream().reduce(Double::sum).orElse(0D) / population;
+ }
+
+ public static double getStdDevHitRatio() {
+ if (population == 0) return 0;
+ if (stdDevHitRatio != null) return stdDevHitRatio;
+ double mean = getAverageHitRatio();
+ double temp = HIT_RATIOS.stream()
+ .map(hitRate -> (hitRate - mean) * (hitRate - mean))
+ .reduce(Double::sum)
+ .orElse(0D);
+ stdDevHitRatio = Math.sqrt(temp / population);
+ return stdDevHitRatio;
+ }
+
+ public static double hitThreshold(int kStdDev) {
+ return getAverageHitRatio() + (kStdDev * getStdDevHitRatio());
+ }
+
+
+ public static double getAverageMissRatio() {
+ if (population == 0) return 0;
+ return BigDecimal.valueOf(MISS_RATIOS.stream().reduce(Double::sum).orElse(0D)).divide(new BigDecimal(population), 5, RoundingMode.HALF_UP).doubleValue();
+ }
+
+ public static double getStdDevMissRatio() {
+ if (population == 0) return 0;
+ if (stdDevMissRatio != null) return stdDevMissRatio;
+ double mean = getAverageMissRatio();
+ double temp = MISS_RATIOS.stream().map(missRatio -> (missRatio - mean) * (missRatio - mean))
+ .reduce(Double::sum)
+ .orElse(0D);
+ stdDevMissRatio = Math.sqrt(temp / population);
+ return stdDevMissRatio;
+ }
+
+ public static double missThreshold(int kStdDev) {
+ return getAverageMissRatio() + (kStdDev * getStdDevMissRatio());
+ }
+
+
+ public static double getAverageExecutionTime() {
+ if (population == 0) return 0;
+ return new BigDecimal(EXECUTION_TIMES.stream().reduce(Long::sum).orElse(0L)).divide(new BigDecimal(population), 5, RoundingMode.HALF_UP).doubleValue();
+ }
+
+ public static double getStdDevExecutionTime() {
+ if (population == 0) return 0;
+ if (stdDevExecutionTime != null) return stdDevExecutionTime;
+ double mean = getAverageExecutionTime();
+ double temp = EXECUTION_TIMES.stream()
+ .map(executionTime -> (executionTime - mean) * (executionTime - mean))
+ .reduce(Double::sum)
+ .orElse(0D);
+ stdDevExecutionTime = Math.sqrt(temp / population);
+ return stdDevExecutionTime;
+ }
+
+ public static double expensivenessThreshold(int kStdDev) {
+ return getAverageExecutionTime() + (kStdDev * getStdDevExecutionTime());
+ }
+
+
+ public static double getAverageShareability() {
+ if (population == 0) return 0;
+ return BigDecimal.valueOf(SHAREABILITIES.stream().reduce(Double::sum).orElse(0D)).divide(new BigDecimal(population), 5, RoundingMode.HALF_UP).doubleValue();
+ }
+
+ public static double getStdDevShareability() {
+ if (population == 0) return 0;
+ if (stdDevShareability != null) return stdDevShareability;
+ double mean = getAverageShareability();
+ double temp = SHAREABILITIES.stream()
+ .map(shareability -> (shareability - mean) * (shareability - mean))
+ .reduce(Double::sum)
+ .orElse(0D);
+ stdDevShareability = Math.sqrt(temp / population);
+ return stdDevShareability;
+ }
+
+ public static double shareabilityThreshold(int kStdDev) {
+ return getAverageShareability() + (kStdDev * getStdDevShareability());
+ }
}
diff --git a/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/Main.java b/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/Main.java
index 6ec6242..d8beda9 100755
--- a/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/Main.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/aplcachetf/Main.java
@@ -13,13 +13,14 @@ import br.ufrgs.inf.prosoft.tfcache.configuration.Arguments;
import br.ufrgs.inf.prosoft.tfcache.configuration.Configuration;
import br.ufrgs.inf.prosoft.trace.Trace;
import br.ufrgs.inf.prosoft.trace.reader.Mode;
+
+import java.text.MessageFormat;
+import java.util.Arrays;
import java.util.List;
import java.util.Map;
-import java.util.logging.Level;
import java.util.logging.Logger;
/**
- *
* @author romulo
*/
public class Main {
@@ -30,7 +31,16 @@ public class Main {
System.setProperty("java.util.logging.SimpleFormatter.format", "[%1$tF %1$tT+%1$tL] [%4$-7s] [APLCacheTF] %5$s %n");
if (args.length < 2) {
- System.err.println("--trace=<TracePath> --output=<OutputPath> [--tfstore=<storePath>] [--tfkernel=<exhaustive|optimised>] [--tfstaleness=<ignore|shrink>] [--mode=<complete|hashed|partial>] [--k=<kStandardDeviation>] [--window=<windowSize>] [--shift=<shiftTime>]");
+ System.err.println("--trace=<TracePath>" +
+ " --output=<OutputPath>" +
+ " [--tfstore=<storePath>]" +
+ " [--tfkernel=<exhaustive|optimised>]" +
+ " [--tfstaleness=<ignore|shrink>]" +
+ " [--mode=<complete|hashed|partial>]" +
+ " [--k=<kStandardDeviation>]" +
+ " [--objective=(savedTime)0..1,0..1(idleTime)]" +
+ " [--window=<windowSize>]" +
+ " [--shift=<shiftTime>]");
System.exit(1);
}
@@ -49,15 +59,15 @@ public class Main {
String mode = arguments.get("mode");
if (mode == null) {
mode = "complete";
- LOGGER.log(Level.INFO, "Using default mode: {0}", mode);
+ LOGGER.info(MessageFormat.format("Using default mode: {0}", mode));
}
int k = 0;
String kStr = arguments.get("k");
if (kStr == null) {
- LOGGER.log(Level.INFO, "Using default k: {0}", k);
+ LOGGER.info(MessageFormat.format("Using default k: {0}", k));
} else {
try {
- k = Integer.valueOf(kStr);
+ k = Integer.parseInt(kStr);
} catch (NumberFormatException ex) {
System.err.println("<k> must be a number");
System.exit(1);
@@ -67,24 +77,26 @@ public class Main {
Long window = null;
try {
window = Long.valueOf(arguments.get("window"));
- } catch (NumberFormatException ex) {
+ } catch (NumberFormatException ignored) {
}
Long shift = null;
try {
shift = Long.valueOf(arguments.get("shift"));
- } catch (NumberFormatException ex) {
+ } catch (NumberFormatException ignored) {
}
- LOGGER.log(Level.INFO, "Reading traces");
+ LOGGER.info("Reading traces");
List<Trace> traces = TraceReader.parseFile(tracePath, Mode.valueOf(mode.toUpperCase()), window, shift);
- LOGGER.log(Level.INFO, "Grouping {0} traces by methods", traces.size());
+ LOGGER.info(MessageFormat.format("Grouping {0} traces by methods", traces.size()));
List<Method> methods = TraceReader.groupByMethods(traces);
- LOGGER.log(Level.INFO, "grouped traces into {0} methods", methods.size());
+ LOGGER.info(MessageFormat.format("grouped traces into {0} methods", methods.size()));
Configuration.setLevel("input");
Configuration.setKernel(arguments.get("tfkernel"));
Configuration.setStaleness(arguments.get("tfstaleness"));
Configuration.setStore(arguments.get("tfstore"));
+ Configuration.setInput(Arrays.stream(tracePath.split("/")).reduce((a, b) -> b).orElse(""));
+ Configuration.setPreferences(arguments.get("objective"));
StorageManager.load();
APLCache aplcache = new APLCache(methods);
aplcache.recommend(k, outputPath);