aplcache

deprecated ttlForInput and replaced for ttl per method on caffeine.

4/3/2021 3:56:18 PM

Details

diff --git a/src/main/java/br/ufrgs/inf/prosoft/aplcache/caching/APLCache.java b/src/main/java/br/ufrgs/inf/prosoft/aplcache/caching/APLCache.java
index d67d5a6..0ffa816 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/aplcache/caching/APLCache.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/aplcache/caching/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.aplcache.caching;
 
 import br.ufrgs.inf.prosoft.cache.Caffeine;
@@ -25,9 +20,10 @@ import java.util.stream.Stream;
 public class APLCache<V> {
 
   private static final Logger LOGGER = Logger.getLogger(APLCache.class.getName());
-  private static final Map<String, Map<String, Long>> APLCACHE_METHOD_HAS_CACHEABLE_PARAMETERS = new HashMap<>();
+
   private static final String APLCACHE_LOG = System.getenv("APLCACHE_LOG") != null && !System.getenv("APLCACHE_LOG").isEmpty() && !System.getenv("APLCACHE_LOG").equals("null")
     ? System.getenv("APLCACHE_LOG") : null;
+  private static final Map<String, Map<String, Long>> APLCACHE_METHOD_HAS_CACHEABLE_PARAMETERS = new HashMap<>();
   private static String APLCACHE_CACHEABLE_PARAMETERS = System.getenv("APLCACHE_CACHEABLE_PARAMETERS");
   private final Caffeine<String, V> caffeine;
 
@@ -47,7 +43,7 @@ public class APLCache<V> {
     this.caffeine = new Caffeine<>(name, ttl);
   }
 
-  private synchronized static void loadCacheableParameters() {
+  private synchronized static void loadCacheableInputs() {
     if (APLCACHE_CACHEABLE_PARAMETERS == null) return;
     try (FileReader fileReader = new FileReader(APLCACHE_CACHEABLE_PARAMETERS)) {
       JsonParser jsonParser = new JsonParser();
@@ -58,46 +54,23 @@ public class APLCache<V> {
         else entry.getValue().getAsJsonObject().entrySet().forEach(innerEntry -> inputsHasTTL.put(innerEntry.getKey(), innerEntry.getValue().getAsLong()));
         APLCACHE_METHOD_HAS_CACHEABLE_PARAMETERS.put(entry.getKey(), inputsHasTTL);
       });
-      LOGGER.log(Level.INFO, "cache file loaded");
+      LOGGER.log(Level.INFO, "cacheable inputs file loaded");
     } catch (IOException ex) {
-      LOGGER.log(Level.SEVERE, "invalid cache file");
+      LOGGER.log(Level.SEVERE, "invalid cacheable inputs file");
     }
     APLCACHE_CACHEABLE_PARAMETERS = null;
   }
 
   private static void log(String message) {
-    if (APLCACHE_LOG == null) {
-      return;
-    }
+    if (APLCACHE_LOG == null) return;
     try (FileWriter fileWriter = new FileWriter(APLCACHE_LOG, true)) {
       fileWriter.write(message + "\n");
-    } catch (IOException ex) {
-    }
-  }
-
-  public boolean isCacheable(Thread currentThread, Object... parameters) {
-    StackTraceElement[] stackTrace = currentThread.getStackTrace();
-    StackTraceElement stackTraceElement;
-    try {
-      stackTraceElement = stackTrace[2];
-    } catch (ArrayIndexOutOfBoundsException ex) {
-      stackTraceElement = stackTrace[0];
-    }
-    return isCacheable(stackTraceElement, parameters);
-  }
-
-  public boolean isCacheable(StackTraceElement stackTraceElement, Object... parameters) {
-    try {
-      String methodName = stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName();
-      methodName = methodName.replace("$", ".");
-      return isCacheable(methodName, parameters);
-    } catch (Exception ex) {
-      return false;
+    } catch (IOException ignored) {
     }
   }
 
-  public boolean isCacheable(String method, Object... parameters) {
-    loadCacheableParameters();
+  public boolean isCacheable(String method, String serialisedParameters) {
+    loadCacheableInputs();
     if (APLCACHE_METHOD_HAS_CACHEABLE_PARAMETERS.isEmpty()) {
       LOGGER.log(Level.WARNING, "no method is cacheable");
       return false;
@@ -107,35 +80,14 @@ public class APLCache<V> {
       LOGGER.log(Level.WARNING, "method not cacheable: {0}", method);
       return false;
     }
-    String serialisedParameters = Stream.of(parameters).map(JSONSerialiser::serialise)
-      .collect(Collectors.joining(",", "[", "]"));
-    if (cacheableInputsHasTTL.containsKey(serialisedParameters)) {
-      return true;
-    }
+    if (cacheableInputsHasTTL.containsKey(serialisedParameters)) return true;
     log(this.caffeine.getCachePerformance().getName() + " : " + serialisedParameters);
     return false;
   }
 
-  public boolean isCacheable(String method, String parameters) {
-    loadCacheableParameters();
-    if (APLCACHE_METHOD_HAS_CACHEABLE_PARAMETERS.isEmpty()) {
-      LOGGER.log(Level.WARNING, "no method is cacheable");
-      return false;
-    }
-    Map<String, Long> cacheableParameters = APLCACHE_METHOD_HAS_CACHEABLE_PARAMETERS.get(method);
-    if (cacheableParameters == null) {
-      LOGGER.log(Level.WARNING, "method not cacheable: {0}", method);
-      return false;
-    }
-    if (cacheableParameters.containsKey(parameters)) {
-      return true;
-    }
-    log(this.caffeine.getCachePerformance().getName() + " : " + parameters);
-    return false;
-  }
-
+  @Deprecated
   public long getTTLforInput(String method, String input) {
-    loadCacheableParameters();
+    loadCacheableInputs();
     if (APLCACHE_METHOD_HAS_CACHEABLE_PARAMETERS.isEmpty()) {
       LOGGER.log(Level.WARNING, "no method is cacheable");
       return 0;
@@ -145,65 +97,43 @@ public class APLCache<V> {
       LOGGER.log(Level.WARNING, "method not cacheable: {0}", method);
       return 0;
     }
-    return cacheableInputsHasTTL.get(input);
+    Long recommendedTTL = cacheableInputsHasTTL.get(input);
+    if (recommendedTTL == null) return 0;
+    return recommendedTTL;
   }
 
   public V computeIfAbsent(Thread currentThread, Object[] parameters, Supplier<V> supplier, long timeToLive) {
-    StackTraceElement[] stackTrace = currentThread.getStackTrace();
-    StackTraceElement stackTraceElement;
-    try {
-      stackTraceElement = stackTrace[2];
-    } catch (ArrayIndexOutOfBoundsException ex) {
-      stackTraceElement = stackTrace[0];
-    }
-    String methodName = stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName();
-    methodName = methodName.replace("$", ".");
-
-    String serialisedParameters = Stream.of(parameters).map(JSONSerialiser::serialise)
-      .collect(Collectors.joining(",", "[", "]"));
-    synchronized (serialisedParameters) {
-      try {
-        return this.caffeine.get(serialisedParameters);
-      } catch (KeyNotFoundException ex) {
-        V get = supplier.get();
-        if (isCacheable(methodName, serialisedParameters)) {
-          long recommendedTTLforInput = getTTLforInput(methodName, serialisedParameters);
-          if (recommendedTTLforInput == 0) this.caffeine.put(serialisedParameters, get, timeToLive);
-          else this.caffeine.put(serialisedParameters, get, recommendedTTLforInput);
-        }
-        return get;
-      }
-    }
+    return computeIfAbsent(currentThread.getStackTrace()[2], parameters, supplier, timeToLive);
   }
 
   public V computeIfAbsent(Thread currentThread, Object[] parameters, Supplier<V> supplier) {
-    StackTraceElement[] stackTrace = currentThread.getStackTrace();
-    StackTraceElement stackTraceElement;
-    try {
-      stackTraceElement = stackTrace[2];
-    } catch (ArrayIndexOutOfBoundsException ex) {
-      stackTraceElement = stackTrace[0];
-    }
+    return computeIfAbsent(currentThread.getStackTrace()[2], parameters, supplier, 0);
+  }
+
+  public V computeIfAbsent(StackTraceElement stackTraceElement, Object[] parameters, Supplier<V> supplier, long timeToLive) {
     String methodName = stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName();
     methodName = methodName.replace("$", ".");
+    return computeIfAbsent(methodName, parameters, supplier, timeToLive);
+  }
 
-    String serialisedParameters = Stream.of(parameters).map(JSONSerialiser::serialise)
-      .collect(Collectors.joining(",", "[", "]"));
+  public V computeIfAbsent(String methodName, Object[] parameters, Supplier<V> supplier) {
+    return computeIfAbsent(methodName, parameters, supplier, 0);
+  }
+
+  public V computeIfAbsent(String methodName, Object[] parameters, Supplier<V> supplier, long timeToLive) {
+    String serialisedParameters = Stream.of(parameters).map(JSONSerialiser::serialise).collect(Collectors.joining(",", "[", "]"));
     synchronized (serialisedParameters) {
       try {
         return this.caffeine.get(serialisedParameters);
       } catch (KeyNotFoundException ex) {
         V get = supplier.get();
         if (isCacheable(methodName, serialisedParameters)) {
-          long ttLforInput = getTTLforInput(methodName, serialisedParameters);
-          if (ttLforInput == 0) {
-            this.caffeine.put(serialisedParameters, get);
-          } else {
-            this.caffeine.put(serialisedParameters, get, ttLforInput);
-          }
+          if (timeToLive != 0) this.caffeine.put(serialisedParameters, get, timeToLive);
+          else this.caffeine.put(serialisedParameters, get);
         }
         return get;
       }
     }
   }
+
 }
diff --git a/src/main/java/br/ufrgs/inf/prosoft/aplcache/metadata/Method.java b/src/main/java/br/ufrgs/inf/prosoft/aplcache/metadata/Method.java
index b305a2f..2898ad0 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/aplcache/metadata/Method.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/aplcache/metadata/Method.java
@@ -6,7 +6,6 @@ import java.util.*;
 import java.util.function.Consumer;
 import java.util.logging.Level;
 import java.util.logging.Logger;
-import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 public class Method {
@@ -42,9 +41,7 @@ public class Method {
     }
 
     public Stream<Occurrence> occurrences() {
-        if (this.occurrences == null) {
-            throw new RuntimeException("Occurrences already consumed");
-        }
+        if (this.occurrences == null) throw new RuntimeException("Occurrences already consumed");
         return this.occurrences.stream();
     }
 
@@ -68,9 +65,7 @@ public class Method {
                 if (TRACER_VERBOSE) {
                     System.out.print(".");
                     System.out.flush();
-                    if (++this.i % 100 == 0) {
-                        System.out.println();
-                    }
+                    if (++this.i % 100 == 0) System.out.println();
                 }
                 String parameters = occurrence.getParametersSerialised();
                 synchronized (groupByParameter) {
@@ -84,31 +79,25 @@ public class Method {
                 }
             }
         });
-        this.groupsOfOccurrences = groupByParameter.values().stream().collect(Collectors.toList());
+        this.groupsOfOccurrences = new ArrayList<>(groupByParameter.values());
     }
 
     public void removeSingleOccurrences() {
-        if (this.groupsOfOccurrences == null) {
-            groupByInput();
-        }
-        int initialCountofOccurrences = this.groupsOfOccurrences.size();
+        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});
-        }
+        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 calculateMetrics() {
-        if (this.groupsOfOccurrences == null) {
-            groupByInput();
-        }
-        Collections.sort(this.groupsOfOccurrences, Comparator.comparingInt(GroupOfOccurrences::getOccurrencesSize));
+        if (this.groupsOfOccurrences == null) groupByInput();
+        this.groupsOfOccurrences.sort(Comparator.comparingInt(GroupOfOccurrences::getOccurrencesSize));
         this.groupsOfOccurrences.stream().parallel().forEach(GroupOfOccurrences::calculateMetrics);
     }
 
     public void calculateThresholds() {
-        this.groupsOfOccurrences.stream().forEach(GroupOfOccurrences::calculateThresholds);
+        this.groupsOfOccurrences.forEach(GroupOfOccurrences::calculateThresholds);
     }
 
     public void filterCacheableInputs() {