I'm using Caffeine lib for caching purposes with 1-sec expiration interval after entry creation. It turned out that entries expire with some delay sometimes it could take up to 2x more time to expire instead of configured 1-sec interval. Based on my experiments executor and scheduler threads count config has no effect on that delay.
There is my test snippet where I measure time spent in cache for the particular entry and print it out:
private final Cache<String, LinkedList<Pair<Long, Long>>> groupedEvents = Caffeine.newBuilder()
.expireAfter(new Expiry<String, LinkedList<Pair<Long, Long>>>() {
public long expireAfterCreate(String key, LinkedList<Pair<Long, Long>> val, long currentTime) {
return TimeUnit.SECONDS.toNanos(1);
}
public long expireAfterUpdate(String key, LinkedList<Pair<Long, Long>> val, long currentTime, long currentDuration) {
return currentDuration;
}
public long expireAfterRead(String key, LinkedList<Pair<Long, Long>> val, long currentTime, long currentDuration) {
return currentDuration;
}
})
.scheduler(Scheduler.forScheduledExecutorService(Executors.newScheduledThreadPool(4)))
.executor(Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2))
.removalListener((key, events, cause) -> {
long timeInCache = System.currentTimeMillis() - events.get(0).getLeft();
System.out.println(String.format("key %s, values count: %s, timeInCache: %s ms",
key, events.size(), timeInCache));
}).build();
@Test
public void test() throws InterruptedException {
for (int i = 0; i < 1000; i++) {
Thread.sleep(30);
String key = String.valueOf(new Random().nextInt(30));
groupedEvents.asMap().compute(key, (s, values) -> {
if (values == null) {
values = new LinkedList<>();
}
values.add(Pair.of(System.currentTimeMillis(), 123L));
return values;
});
}
Output is the following:
key 10, values count: 1, timeInCache: 1223 ms
key 0, values count: 3, timeInCache: 1470 ms
key 20, values count: 1, timeInCache: 2295 ms
key 15, values count: 2, timeInCache: 2325 ms
key 16, values count: 1, timeInCache: 2023 ms
key 23, values count: 1, timeInCache: 1566 ms
key 18, values count: 1, timeInCache: 2052 ms
key 14, values count: 2, timeInCache: 1079 ms
key 3, values count: 3, timeInCache: 1628 ms
key 4, values count: 2, timeInCache: 1109 ms
key 2, values count: 2, timeInCache: 1841 ms
key 17, values count: 1, timeInCache: 1535 ms
key 13, values count: 2, timeInCache: 1011 ms
key 7, values count: 1, timeInCache: 1471 ms
key 12, values count: 1, timeInCache: 1441 ms
As you see the load is not high and around 33 entry addition per sec (based on the Thread.sleep(30)) but for some entries, it takes up to ~2300ms instead of the desired 1sec to expire after creation and that delay is critical for my application since the end-user will not get my data within 1-1.3 sec interval.
Is there any chance to tune that entry eviction time to reduce the delay? Im using latest 'com.github.ben-manes.caffeine:caffeine:2.8.5'' version