Details
diff --git a/src/main/java/br/ufrgs/inf/prosoft/cache/CachePerformance.java b/src/main/java/br/ufrgs/inf/prosoft/cache/CachePerformance.java
index cf0e9ed..887c7af 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/cache/CachePerformance.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/cache/CachePerformance.java
@@ -69,8 +69,6 @@ public class CachePerformance {
this.invalidations++;
this.bytesInvalidated += size;
break;
- default:
- throw new AssertionError(type.name());
}
CacheEvent cacheEvent = new CacheEvent(type, this.name, identifier, size);
logCacheEvent(cacheEvent);
diff --git a/src/main/java/br/ufrgs/inf/prosoft/cache/Caffeine.java b/src/main/java/br/ufrgs/inf/prosoft/cache/Caffeine.java
index 9f2c229..279ae7b 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/cache/Caffeine.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/cache/Caffeine.java
@@ -6,11 +6,15 @@
package br.ufrgs.inf.prosoft.cache;
import com.github.benmanes.caffeine.cache.Expiry;
+import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
@@ -20,13 +24,14 @@ import java.util.stream.Collectors;
* @param <K>
* @param <V>
*/
-public class Caffeine<K, V> implements Cache<K, V> {
+public class Caffeine<K, V> implements Cache<K, V>, AutoCloseable {
private static final boolean CACHE_EVALUATE_PERFORMANCE = System.getenv("CACHE_EVENTS") == null || !System.getenv("CACHE_EVENTS").equals("false");
private static final boolean CACHE_REGISTER_SIZE = System.getenv("CACHE_REGISTER_SIZE") != null && System.getenv("CACHE_REGISTER_SIZE").equals("true");
private final com.github.benmanes.caffeine.cache.Cache<Optional<K>, Optional<V>> cache;
private final ConcurrentHashMap<Optional<K>, Long> keyHasTTL;
private final CachePerformance cachePerformance;
+ private final ScheduledExecutorService sizeMonitor;
public Caffeine() {
this(new CachePerformance());
@@ -94,6 +99,22 @@ public class Caffeine<K, V> implements Cache<K, V> {
registerEvent(EventType.INVALIDATION, v.orElse(null));
});
this.cache = builder.build();
+
+ this.sizeMonitor = Executors.newScheduledThreadPool(0);
+ if (Caffeine.CACHE_EVALUATE_PERFORMANCE) {
+ this.sizeMonitor.scheduleAtFixedRate(() -> {
+ this.cachePerformance.registerEvent(EventType.POPULATION, String.valueOf(size()));
+ }, 0, 1, TimeUnit.SECONDS);
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException ex) {
+ }
+ this.sizeMonitor.shutdown();
}
public CachePerformance getCachePerformance() {
@@ -153,18 +174,18 @@ public class Caffeine<K, V> implements Cache<K, V> {
}
public int size() {
- return values().size();
+ return this.cache.asMap().size();
}
public boolean isEmpty() {
- return values().isEmpty();
+ return this.cache.asMap().isEmpty();
}
private String getIdentifier(Object object) {
return object != null ? String.valueOf(object.hashCode()) : "null";
}
- protected void registerEvent(EventType eventType, Object object) {
+ private void registerEvent(EventType eventType, Object object) {
if (!CACHE_EVALUATE_PERFORMANCE) {
return;
}
@@ -175,7 +196,7 @@ public class Caffeine<K, V> implements Cache<K, V> {
this.cachePerformance.registerEvent(eventType, identifier);
}
if (eventType.equals(EventType.ADDITION)) {
- this.cachePerformance.registerSize((int) this.cache.stats().loadCount());
+ this.cachePerformance.registerSize(size());
}
}
diff --git a/src/main/java/br/ufrgs/inf/prosoft/cache/CaffeineSingleCache.java b/src/main/java/br/ufrgs/inf/prosoft/cache/CaffeineSingleCache.java
index ae312d8..6e32697 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/cache/CaffeineSingleCache.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/cache/CaffeineSingleCache.java
@@ -29,10 +29,4 @@ public class CaffeineSingleCache<K, V> extends Caffeine<K, V> {
super(cachingPerformance, ttl, 1L);
}
- @Override
- public void put(K key, V value) {
- registerEvent(EventType.INVALIDATION, null);
- super.put(key, value);
- }
-
}
diff --git a/src/main/java/br/ufrgs/inf/prosoft/cache/EventType.java b/src/main/java/br/ufrgs/inf/prosoft/cache/EventType.java
index 4507fb5..f80036b 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/cache/EventType.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/cache/EventType.java
@@ -10,5 +10,5 @@ package br.ufrgs.inf.prosoft.cache;
* @author romulo
*/
public enum EventType {
- HIT, MISS, ADDITION, INVALIDATION;
+ HIT, MISS, ADDITION, INVALIDATION, POPULATION;
}
diff --git a/src/main/java/br/ufrgs/inf/prosoft/cache/tools/Reducer.java b/src/main/java/br/ufrgs/inf/prosoft/cache/tools/Reducer.java
index 9044da2..549e7da 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/cache/tools/Reducer.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/cache/tools/Reducer.java
@@ -13,9 +13,8 @@ import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.Map;
-import java.util.TreeMap;
+import java.util.function.Consumer;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Stream;
@@ -61,65 +60,25 @@ public class Reducer {
public static void size(String eventsPath, String reducePath, String prefix) {
try (Stream<String> lines = Files.lines(Paths.get(eventsPath))) {
Gson gson = new Gson();
- Map<String, TreeMap<Long, Integer>> cacheHasSizeAlongTime = new HashMap<>();
- lines.forEach(line -> {
- CacheEvent event = gson.fromJson(line, CacheEvent.class);
- if (!(event.getType().equals(EventType.ADDITION) || event.getType().equals(EventType.INVALIDATION))) {
- return;
- }
- cacheHasSizeAlongTime.compute(event.getName(), (key, previous) -> {
- if (previous == null) {
- previous = new TreeMap<>();
- }
- previous.compute(event.getTime() / 1000, (innerKey, innerPrevious) -> {
- if (innerPrevious == null) {
- innerPrevious = 0;
- }
- if (event.getType().equals(EventType.ADDITION)) {
- return innerPrevious + 1;
- }
- return innerPrevious - 1;
- });
- return previous;
- });
- });
+ lines.forEach(new Consumer<String>() {
+ int second = 0;
- cacheHasSizeAlongTime.forEach((name, sizeAlongTime) -> {
- Iterator<Map.Entry<Long, Integer>> iterator = sizeAlongTime.entrySet().iterator();
- int accumulated = iterator.next().getValue();
- while (iterator.hasNext()) {
- Map.Entry<Long, Integer> entry = iterator.next();
- accumulated += entry.getValue();
- if (accumulated < 0) {
- accumulated = 0;
+ @Override
+ public void accept(String line) {
+ CacheEvent event = gson.fromJson(line, CacheEvent.class);
+ if (!event.getType().equals(EventType.POPULATION)) {
+ return;
}
- entry.setValue(accumulated);
- }
- });
-
- final Long baseTime = cacheHasSizeAlongTime.values().stream().map(map -> map.firstKey()).min(Long::compare).orElse(0L);
- final Long adjustedMaxTime = cacheHasSizeAlongTime.values().stream().map(map -> map.lastKey()).max(Long::compare).orElse(0L) - baseTime;
-
- try (FileWriter fileWriter = new FileWriter(reducePath, true)) {
- cacheHasSizeAlongTime.forEach((name, sizeAlongTime) -> {
- try {
- Map.Entry<Long, Integer> pollFirstEntry = sizeAlongTime.pollFirstEntry();
- for (long i = 0; i < pollFirstEntry.getKey() - baseTime; i++) {
- fileWriter.write(prefix + name + "," + i + "," + 0 + "\n");
- }
- for (long i = pollFirstEntry.getKey() - baseTime; i <= adjustedMaxTime; i++) {
- if (sizeAlongTime.size() > 1 && i > pollFirstEntry.getKey() - baseTime) {
- pollFirstEntry = sizeAlongTime.pollFirstEntry();
- }
- fileWriter.write(prefix + name + "," + i + "," + pollFirstEntry.getValue() + "\n");
- }
+ try (FileWriter fileWriter = new FileWriter(reducePath, true)) {
+ fileWriter.write(prefix + event.getName() + "," + this.second + "," + event.getIdentifier() + "\n");
} catch (IOException ex) {
- LOGGER.log(Level.SEVERE, "file not found {0}", reducePath);
+ LOGGER.log(Level.SEVERE, "output error {0}", eventsPath);
}
- });
- }
+ this.second++;
+ }
+ });
} catch (IOException ex) {
- LOGGER.log(Level.SEVERE, "file not found {0}", eventsPath);
+ LOGGER.log(Level.SEVERE, "input not found {0}", eventsPath);
}
}