tfcache

Details

diff --git a/src/main/java/br/ufrgs/inf/prosoft/tfcache/configuration/Configuration.java b/src/main/java/br/ufrgs/inf/prosoft/tfcache/configuration/Configuration.java
index 10ddb8c..a0f1548 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/tfcache/configuration/Configuration.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/tfcache/configuration/Configuration.java
@@ -16,6 +16,7 @@ public class Configuration {
     private static String changeability = "allow";
     private static String staleness = "ignore";
     private static String kernel = "exhaustive";
+    private static boolean verbose = false;
 
     public static void setLevel(String level) {
         if (level == null) {
@@ -81,7 +82,7 @@ public class Configuration {
             LOGGER.log(Level.INFO, "Using default kernel: {0}", Configuration.kernel);
             return;
         }
-        if (!kernel.equals("exhaustive") && !kernel.equals("optimised")) {
+        if (!kernel.equals("exhaustive") && !kernel.equals("optimised") && !kernel.equals("test")) {
             LOGGER.log(Level.SEVERE, "Unrecognised option for kernel");
             System.exit(1);
         }
@@ -92,4 +93,19 @@ public class Configuration {
         return kernel;
     }
 
+    public static void setVerbose(String verbose) {
+        if (verbose == null) {
+            return;
+        }
+        if (!verbose.equals("true") && !verbose.equals("false")) {
+            LOGGER.log(Level.SEVERE, "Unrecognised option for verbose");
+            System.exit(1);
+        }
+        Configuration.verbose = verbose.equals("true");
+    }
+
+    public static boolean getVerbose() {
+        return verbose;
+    }
+
 }
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 f7ac970..b4e039c 100755
--- a/src/main/java/br/ufrgs/inf/prosoft/tfcache/Main.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/tfcache/Main.java
@@ -28,7 +28,7 @@ public class Main {
         System.setProperty("java.util.logging.SimpleFormatter.format", "[%1$tF %1$tT+%1$tL] [%4$-7s] [TFCache] %5$s %n");
 
         if (args.length < 1) {
-            System.err.println("--trace=<TracePath> [--level=<method|input>] [--output=<outputPath>] [--changeability=<allow|deny>] [--staleness=<ignore|shrink>] [--kernel=<exhaustive|optimised>]");
+            System.err.println("--trace=<TracePath> [--level=<method|input>] [--output=<outputPath>] [--changeability=<allow|deny>] [--staleness=<ignore|shrink>] [--kernel=<exhaustive|optimised>|test] [--verbose=<false|true>]");
             System.exit(1);
         }
 
@@ -60,6 +60,7 @@ public class Main {
         Configuration.setChangeability(arguments.get("changeability"));
         Configuration.setStaleness(arguments.get("staleness"));
         Configuration.setKernel(arguments.get("kernel"));
+        Configuration.setVerbose(arguments.get("verbose"));
 
         LOGGER.log(Level.INFO, "Reading traces");
         List<Trace> traces = TraceReader.parseFile(tracePath);
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 29d3783..49384f3 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
@@ -7,6 +7,7 @@ package br.ufrgs.inf.prosoft.tfcache.metadata;
 
 import br.ufrgs.inf.prosoft.tfcache.Metrics;
 import br.ufrgs.inf.prosoft.tfcache.Simulator;
+import br.ufrgs.inf.prosoft.tfcache.configuration.Configuration;
 import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -98,8 +99,17 @@ public class Method {
         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 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<>();
-        this.occurrences.stream().forEach(occurrence -> {
+        occurrences.stream().forEach(occurrence -> {
             String parameters = occurrence.getParametersSerialised();
 
             inputHasOccurrences.compute(parameters, (key, oldValue) -> {
@@ -110,9 +120,7 @@ public class Method {
                 return oldValue;
             });
         });
-        this.groupsOfOccurrences = inputHasOccurrences.entrySet().stream()
-                .map(entry -> new GroupOfOccurrences(entry.getKey(), entry.getValue()))
-                .collect(Collectors.toList());
+        return inputHasOccurrences;
     }
 
     public void removeChangeableInputs() {
@@ -195,6 +203,9 @@ public class Method {
             groupByInput();
             removeSingleOccurrences();
         }
+        if (Configuration.getVerbose()) {
+            System.out.println("=== " + getName() + " ===");
+        }
         groupsOfOccurrences().parallel().forEach(GroupOfOccurrences::calculateHitsPerTimeInCache);
         if (this.bestMetrics == null) {
             long savedTime = groupsOfOccurrences().map(GroupOfOccurrences::getSavedTime).reduce(Long::sum).get();
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 bdc912b..ed926f7 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/tfcache/Simulator.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/tfcache/Simulator.java
@@ -6,8 +6,10 @@
 package br.ufrgs.inf.prosoft.tfcache;
 
 import br.ufrgs.inf.prosoft.tfcache.configuration.Configuration;
+import br.ufrgs.inf.prosoft.tfcache.metadata.Method;
 import br.ufrgs.inf.prosoft.tfcache.metadata.Occurrence;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -35,15 +37,25 @@ public class Simulator {
         return metrics;
     }
 
+    public void simulate(List<Occurrence> occurrences) {
+        simulate(occurrences, this.metrics);
+    }
+
     public void simulate(Stream<Occurrence> occurrences, long ttl) {
         simulate(occurrences, ttl, this.metrics);
     }
 
     public static void simulate(List<Occurrence> occurrences, Metrics metrics) {
-        if (Configuration.getKernel().equals("exhaustive")) {
-            simulate(occurrences, generateAllTTLs(occurrences), metrics);
-        } else {
-            simulate(occurrences, generateTTLsOfInterest(occurrences), metrics);
+        switch (Configuration.getKernel()) {
+            case "exhaustive":
+                simulate(occurrences, generateAllTTLs(occurrences), metrics);
+                break;
+            case "optimised":
+                simulate(occurrences, generateTTLsOfInterest(occurrences), metrics);
+                break;
+            default:
+                testKernels(occurrences);
+                break;
         }
     }
 
@@ -134,4 +146,50 @@ public class Simulator {
         return LongStream.rangeClosed(minTTL, maxTTL).boxed().parallel();
     }
 
+    private static void testKernels(List<Occurrence> occurrences) {
+        Metrics optimisedMetrics = new Metrics();
+
+        Map<String, List<Occurrence>> inputHasOccurrences = Method.groupByInput(occurrences);
+        Set<Long> ttlsOfInterest = inputHasOccurrences.values().stream()
+                .map(Simulator::generateTTLsOfInterest)
+                .reduce(Stream::concat)
+                .get()
+                .collect(Collectors.toSet());
+        simulate(occurrences, ttlsOfInterest.stream(), optimisedMetrics);
+
+        List<Metrics> exhaustiveMetrics = Collections.synchronizedList(new ArrayList<>());
+        generateAllTTLs(occurrences).forEach(actualTTL -> {
+            Metrics partialMetrics = new Metrics();
+            exhaustiveMetrics.add(partialMetrics);
+            simulate(occurrences.stream(), actualTTL, partialMetrics);
+        });
+
+        Metrics.removeDominatedMetrics(exhaustiveMetrics);
+        List<Long> missingTTLs = exhaustiveMetrics.stream().map(metrics -> metrics.getTtl())
+                .filter(ttl -> !ttlsOfInterest.contains(ttl))
+                .sorted()
+                .collect(Collectors.toList());
+        if (!missingTTLs.isEmpty()) {
+            System.out.println("\tMissing ttls: " + missingTTLs);
+        }
+
+        Metrics maxExhaustiveMetrics = exhaustiveMetrics.stream().max(Metrics::compareTo).orElse(new Metrics());
+        if (maxExhaustiveMetrics.getTtl() != optimisedMetrics.getTtl()) {
+            System.out.println("\tDIFFERENT BEST METRICS");
+            System.out.println("\tOptimised: " + optimisedMetrics);
+            System.out.println("\tExhaustive: " + maxExhaustiveMetrics);
+            switch (maxExhaustiveMetrics.compareTo(optimisedMetrics)) {
+                case -1:
+                    System.out.println("\tOptimised won");
+                    break;
+                case 1:
+                    System.out.println("\tExhaustive won");
+                    break;
+                default:
+                    System.out.println("\tEquivalent recommendation");
+                    break;
+            }
+        }
+    }
+
 }
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 c3b4b39..a74a2e6 100755
--- a/src/main/java/br/ufrgs/inf/prosoft/tfcache/TFCache.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/tfcache/TFCache.java
@@ -88,15 +88,17 @@ public class TFCache {
                     + " Saves " + method.getSavedTime()
                     + " Hits " + method.getBestMetrics().getHits()
                     + " Stales " + method.getBestMetrics().getStales());
-            method.groupsOfOccurrences().forEach(group -> {
-                System.out.println("\t" + group.getParameters().hashCode()
-                        + " Occurrences " + group.getOccurrencesSize()
-                        + " -> TTL " + group.getTtl()
-                        + " STpTiC " + group.getSavedTimePerTimeInCache()
-                        + " Saves " + group.getSavedTime()
-                        + " Hits " + group.getBestMetrics().getHits()
-                        + " Stales " + group.getBestMetrics().getHits());
-            });
+            if (Configuration.getVerbose()) {
+                method.groupsOfOccurrences().forEach(group -> {
+                    System.out.println("\t" + group.getParameters().hashCode()
+                            + " Occurrences " + group.getOccurrencesSize()
+                            + " -> TTL " + group.getTtl()
+                            + " STpTiC " + group.getSavedTimePerTimeInCache()
+                            + " Saves " + group.getSavedTime()
+                            + " Hits " + group.getBestMetrics().getHits()
+                            + " Stales " + group.getBestMetrics().getHits());
+                });
+            }
         });
         try (FileWriter fileWriter = new FileWriter(Configuration.getOutput())) {
             JsonObject jsonCacheableParameters = new JsonObject();