Switch all Guava Cache uses to Caffeine

This commit is contained in:
Andrew Steinborn 2023-01-01 19:05:13 -05:00
parent aaa24752ac
commit 7ed422b4ed
5 changed files with 21 additions and 34 deletions

View File

@ -17,8 +17,8 @@
package com.velocitypowered.proxy.network.netty;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import io.netty.resolver.AddressResolver;
@ -62,7 +62,7 @@ public final class SeparatePoolInetNameResolver extends InetNameResolver {
.setDaemon(true)
.build());
this.delegate = new DefaultNameResolver(executor);
this.cache = CacheBuilder.newBuilder()
this.cache = Caffeine.newBuilder()
.expireAfterWrite(30, TimeUnit.SECONDS)
.build();
}

View File

@ -20,8 +20,8 @@ package com.velocitypowered.proxy.protocol.netty;
import static com.velocitypowered.api.event.query.ProxyQueryEvent.QueryType.BASIC;
import static com.velocitypowered.api.event.query.ProxyQueryEvent.QueryType.FULL;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.google.common.collect.ImmutableSet;
import com.velocitypowered.api.event.query.ProxyQueryEvent;
import com.velocitypowered.api.network.ProtocolVersion;
@ -73,7 +73,7 @@ public class GameSpyQueryHandler extends SimpleChannelInboundHandler<DatagramPac
"hostip"
);
private final Cache<InetAddress, Integer> sessions = CacheBuilder.newBuilder()
private final Cache<InetAddress, Integer> sessions = Caffeine.newBuilder()
.expireAfterWrite(30, TimeUnit.SECONDS)
.build();
private final SecureRandom random;

View File

@ -17,35 +17,33 @@
package com.velocitypowered.proxy.util.ratelimit;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.Ticker;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.base.Ticker;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import java.net.InetAddress;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
/**
* A simple rate-limiter based on a Guava {@link Cache}.
* A simple rate-limiter based on a Caffeine {@link Cache}.
*/
public class GuavaCacheRatelimiter implements Ratelimiter {
public class CaffeineCacheRatelimiter implements Ratelimiter {
private final Cache<InetAddress, Long> expiringCache;
private final long timeoutNanos;
GuavaCacheRatelimiter(long time, TimeUnit unit) {
CaffeineCacheRatelimiter(long time, TimeUnit unit) {
this(time, unit, Ticker.systemTicker());
}
@VisibleForTesting
GuavaCacheRatelimiter(long time, TimeUnit unit, Ticker ticker) {
CaffeineCacheRatelimiter(long time, TimeUnit unit, Ticker ticker) {
Preconditions.checkNotNull(unit, "unit");
Preconditions.checkNotNull(ticker, "ticker");
this.timeoutNanos = unit.toNanos(time);
this.expiringCache = CacheBuilder.newBuilder()
this.expiringCache = Caffeine.newBuilder()
.ticker(ticker)
.concurrencyLevel(Runtime.getRuntime().availableProcessors())
.expireAfterWrite(time, unit)
.build();
}
@ -60,13 +58,7 @@ public class GuavaCacheRatelimiter implements Ratelimiter {
public boolean attempt(InetAddress address) {
Preconditions.checkNotNull(address, "address");
long expectedNewValue = System.nanoTime() + timeoutNanos;
long last;
try {
last = expiringCache.get(address, () -> expectedNewValue);
} catch (ExecutionException e) {
// It should be impossible for this to fail.
throw new AssertionError(e);
}
long last = expiringCache.get(address, (address1) -> expectedNewValue);
return expectedNewValue == last;
}
}

View File

@ -29,7 +29,7 @@ public final class Ratelimiters {
}
public static Ratelimiter createWithMilliseconds(long ms) {
return ms <= 0 ? NoopCacheRatelimiter.INSTANCE : new GuavaCacheRatelimiter(ms,
return ms <= 0 ? NoopCacheRatelimiter.INSTANCE : new CaffeineCacheRatelimiter(ms,
TimeUnit.MILLISECONDS);
}
}

View File

@ -20,17 +20,17 @@ package com.velocitypowered.proxy.util.ratelimit;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import com.google.common.base.Ticker;
import com.github.benmanes.caffeine.cache.Ticker;
import java.net.InetAddress;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import org.junit.jupiter.api.Test;
class GuavaCacheRatelimiterTest {
class CaffeineCacheRatelimiterTest {
@Test
void attemptZero() {
Ratelimiter noRatelimiter = new GuavaCacheRatelimiter(0, TimeUnit.MILLISECONDS);
Ratelimiter noRatelimiter = new CaffeineCacheRatelimiter(0, TimeUnit.MILLISECONDS);
assertTrue(noRatelimiter.attempt(InetAddress.getLoopbackAddress()));
assertTrue(noRatelimiter.attempt(InetAddress.getLoopbackAddress()));
}
@ -39,13 +39,8 @@ class GuavaCacheRatelimiterTest {
void attemptOne() {
long base = System.nanoTime();
AtomicLong extra = new AtomicLong();
Ticker testTicker = new Ticker() {
@Override
public long read() {
return base + extra.get();
}
};
Ratelimiter ratelimiter = new GuavaCacheRatelimiter(1000, TimeUnit.MILLISECONDS, testTicker);
Ticker testTicker = () -> base + extra.get();
Ratelimiter ratelimiter = new CaffeineCacheRatelimiter(1000, TimeUnit.MILLISECONDS, testTicker);
assertTrue(ratelimiter.attempt(InetAddress.getLoopbackAddress()));
assertFalse(ratelimiter.attempt(InetAddress.getLoopbackAddress()));
extra.addAndGet(TimeUnit.SECONDS.toNanos(2));