perf: add cache for replay api

This commit is contained in:
Helvetica Volubi
2026-01-28 22:45:50 +08:00
parent d950c6d3e8
commit 2960e7d24f
3 changed files with 97 additions and 1 deletions
@@ -0,0 +1,34 @@
package fun.bm.lophine.config.modules.function;
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
import fun.bm.lophine.utils.RandomProfilePool;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.HotReloadUnsupported;
import me.earthme.luminol.enums.EnumConfigCategory;
import org.jetbrains.annotations.Nullable;
import java.util.Set;
@ConfigClassInfo(category = EnumConfigCategory.FUNCTION, name = "replay-api")
public class ReplayAPIConfig implements IConfigModule {
@HotReloadUnsupported
@ConfigInfo(name = "enable-cache")
public static boolean enableCache = true;
@HotReloadUnsupported
@ConfigInfo(name = "cache-photographer-time", comments = """
Time to cache photographer profile(in seconds)""")
public static int cachePhotographerTime = 3600;
@HotReloadUnsupported
@ConfigInfo(name = "cache-photographer-size", comments = """
Maximum size of cache photographer profile""")
public static int cachePhotographerSize = 100;
@Override
public void onLoaded(CommentedFileConfig configInstance, @Nullable Set<Exception> e) {
RandomProfilePool.init();
}
}
@@ -0,0 +1,59 @@
package fun.bm.lophine.utils;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.mojang.authlib.GameProfile;
import fun.bm.lophine.config.modules.function.ReplayAPIConfig;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
public class RandomProfilePool {
private static int lastUsedId = 0;
private static final Object lock = new Object();
private static Cache<Integer, GameProfile> cache;
private static final Object lockCache = new Object();
public static void init() {
if (ReplayAPIConfig.enableCache) {
cache = CacheBuilder.newBuilder()
.maximumSize(ReplayAPIConfig.cachePhotographerSize)
.expireAfterWrite(ReplayAPIConfig.cachePhotographerTime, TimeUnit.SECONDS)
.build();
}
}
public static GameProfile getRandomProfile(String id) {
if (ReplayAPIConfig.enableCache) {
synchronized (lockCache) {
for (Map.Entry<Integer, GameProfile> entry : cache.asMap().entrySet()) {
int key = entry.getKey();
cache.invalidate(key);
GameProfile gp = entry.getValue();
return new GameProfile(gp.id(), id, gp.properties());
}
}
}
return new GameProfile(UUID.randomUUID(), id);
}
public static void putProfile(GameProfile profile) {
if (ReplayAPIConfig.enableCache) {
synchronized (lockCache) {
cache.put(getNextId(), profile);
}
}
}
private static int getNextId() {
synchronized (lock) {
int newId = lastUsedId + 1;
while (cache.getIfPresent(newId) != null) {
newId++;
}
lastUsedId = newId;
return newId;
}
}
}
@@ -19,6 +19,7 @@ package org.leavesmc.leaves.replay;
import ca.spottedleaf.moonrise.common.util.TickThread;
import com.mojang.authlib.GameProfile;
import fun.bm.lophine.utils.RandomProfilePool;
import io.papermc.paper.threadedregions.RegionizedServer;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ClientInformation;
@@ -38,6 +39,7 @@ import org.leavesmc.leaves.entity.photographer.Photographer;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -70,7 +72,7 @@ public class ServerPhotographer extends ServerPlayer {
MinecraftServer server = MinecraftServer.getServer();
ServerLevel world = ((CraftWorld) state.loc.getWorld()).getHandle();
GameProfile profile = new GameProfile(UUID.randomUUID(), state.id);
GameProfile profile = RandomProfilePool.getRandomProfile(state.id); // Lophine - add cache
ServerPhotographer photographer = new ServerPhotographer(server, world, profile);
photographer.absSnapTo(state.loc.x(), state.loc.y(), state.loc.z(), state.loc.getYaw(), state.loc.getPitch());
@@ -165,6 +167,7 @@ public class ServerPhotographer extends ServerPlayer {
photographers.remove(this);
MinecraftServer.getServer().getPlayerList().removePhotographer(this);
RandomProfilePool.putProfile(this.gameProfile); // Lophine - add cache
if (!recorder.isSaved()) {
CompletableFuture<Void> future = recorder.saveRecording(saveFile, save);
if (!async) {