Use google common cache instead of our own dirty solution

This commit is contained in:
themode 2021-02-22 08:41:38 +01:00
parent 77148338b9
commit 04b5a4f166
4 changed files with 14 additions and 45 deletions

View File

@ -44,7 +44,6 @@ import net.minestom.server.storage.StorageManager;
import net.minestom.server.timer.SchedulerManager; import net.minestom.server.timer.SchedulerManager;
import net.minestom.server.utils.MathUtils; import net.minestom.server.utils.MathUtils;
import net.minestom.server.utils.PacketUtils; import net.minestom.server.utils.PacketUtils;
import net.minestom.server.utils.cache.TemporaryCache;
import net.minestom.server.utils.thread.MinestomThread; import net.minestom.server.utils.thread.MinestomThread;
import net.minestom.server.utils.validate.Check; import net.minestom.server.utils.validate.Check;
import net.minestom.server.world.Difficulty; import net.minestom.server.world.Difficulty;
@ -794,7 +793,6 @@ public final class MinecraftServer {
LOGGER.info("Shutting down all thread pools."); LOGGER.info("Shutting down all thread pools.");
benchmarkManager.disable(); benchmarkManager.disable();
commandManager.stopConsoleThread(); commandManager.stopConsoleThread();
TemporaryCache.REMOVER_SERVICE.shutdown();
MinestomThread.shutdownAll(); MinestomThread.shutdownAll();
LOGGER.info("Minestom server stopped successfully."); LOGGER.info("Minestom server stopped successfully.");
} }

View File

@ -121,21 +121,20 @@ public class NettyPlayerConnection extends PlayerConnection {
if (getPlayer() != null) { if (getPlayer() != null) {
// Flush happen during #update() // Flush happen during #update()
if (serverPacket instanceof CacheablePacket && MinecraftServer.hasPacketCaching()) { if (serverPacket instanceof CacheablePacket && MinecraftServer.hasPacketCaching()) {
CacheablePacket cacheablePacket = (CacheablePacket) serverPacket; final CacheablePacket cacheablePacket = (CacheablePacket) serverPacket;
final UUID identifier = cacheablePacket.getIdentifier(); final UUID identifier = cacheablePacket.getIdentifier();
if (identifier == null) { if (identifier == null) {
// This packet explicitly said to do not retrieve the cache // This packet explicitly asks to do not retrieve the cache
write(serverPacket); write(serverPacket);
} else { } else {
// Try to retrieve the cached buffer // Try to retrieve the cached buffer
TemporaryCache<ByteBuf> temporaryCache = cacheablePacket.getCache(); TemporaryCache<ByteBuf> temporaryCache = cacheablePacket.getCache();
ByteBuf buffer = temporaryCache.retrieve(identifier, cacheablePacket.getLastUpdateTime()); ByteBuf buffer = temporaryCache.retrieve(identifier);
if (buffer == null) { if (buffer == null) {
// Buffer not found, create and cache it // Buffer not found, create and cache it
final long time = System.currentTimeMillis();
buffer = PacketUtils.createFramedPacket(serverPacket, false); buffer = PacketUtils.createFramedPacket(serverPacket, false);
temporaryCache.cacheObject(identifier, buffer, time); temporaryCache.cache(identifier, buffer);
} }
FramedPacket framedPacket = new FramedPacket(buffer); FramedPacket framedPacket = new FramedPacket(buffer);
write(framedPacket); write(framedPacket);

View File

@ -10,8 +10,7 @@ import java.util.UUID;
* Implemented by {@link ServerPacket server packets} which can be temporary cached in memory to be re-sent later * Implemented by {@link ServerPacket server packets} which can be temporary cached in memory to be re-sent later
* without having to go through all the writing and compression. * without having to go through all the writing and compression.
* <p> * <p>
* {@link #getIdentifier()} is to differenciate this packet from the others of the same type, * {@link #getIdentifier()} is to differentiate this packet from the others of the same type.
* and {@link #getLastUpdateTime()} to know if one packet is newer than the previous one.
*/ */
public interface CacheablePacket { public interface CacheablePacket {
@ -35,11 +34,4 @@ public interface CacheablePacket {
@Nullable @Nullable
UUID getIdentifier(); UUID getIdentifier();
/**
* Gets the last time this packet changed.
*
* @return the last packet update time in milliseconds
*/
long getLastUpdateTime();
} }

View File

@ -1,12 +1,11 @@
package net.minestom.server.utils.cache; package net.minestom.server.utils.cache;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/** /**
@ -16,13 +15,7 @@ import java.util.concurrent.TimeUnit;
*/ */
public class TemporaryCache<T> { public class TemporaryCache<T> {
public static final ScheduledExecutorService REMOVER_SERVICE = Executors.newScheduledThreadPool(1); private final Cache<UUID, T> cache;
// Identifier = Cached object
protected ConcurrentHashMap<UUID, T> cache = new ConcurrentHashMap<>();
// Identifier = time
protected ConcurrentHashMap<UUID, Long> cacheTime = new ConcurrentHashMap<>();
private final long keepTime; private final long keepTime;
/** /**
@ -33,12 +26,9 @@ public class TemporaryCache<T> {
*/ */
public TemporaryCache(long keepTime) { public TemporaryCache(long keepTime) {
this.keepTime = keepTime; this.keepTime = keepTime;
REMOVER_SERVICE.scheduleAtFixedRate(() -> { this.cache = CacheBuilder.newBuilder()
final boolean removed = cacheTime.values().removeIf(time -> System.currentTimeMillis() > time + keepTime); .expireAfterWrite(keepTime, TimeUnit.MILLISECONDS)
if (removed) { .build();
this.cache.entrySet().removeIf(entry -> !cacheTime.containsKey(entry.getKey()));
}
}, keepTime, keepTime, TimeUnit.MILLISECONDS);
} }
/** /**
@ -46,30 +36,20 @@ public class TemporaryCache<T> {
* *
* @param identifier the object identifier * @param identifier the object identifier
* @param value the object to cache * @param value the object to cache
* @param time the current time in milliseconds
*/ */
public void cacheObject(@NotNull UUID identifier, T value, long time) { public void cache(@NotNull UUID identifier, T value) {
this.cache.put(identifier, value); this.cache.put(identifier, value);
this.cacheTime.put(identifier, time);
} }
/** /**
* Retrieves an object from cache. * Retrieves an object from cache.
* *
* @param identifier the object identifier * @param identifier the object identifier
* @param lastUpdate the last update time of your identifier's object,
* used to see if the cached value is up-to-date
* @return the retrieved object or null if not found * @return the retrieved object or null if not found
*/ */
@Nullable @Nullable
public T retrieve(@NotNull UUID identifier, long lastUpdate) { public T retrieve(@NotNull UUID identifier) {
Long tempL = cacheTime.get(identifier); return cache.getIfPresent(identifier);
if (tempL == null) {
return null;
}
//cache.get(identifier) will return null if the race condition occurred which is what we want
return lastUpdate <= tempL ? cache.get(identifier) : null;
} }
/** /**