From fb30820e2bc2864490f383e8922fa0cfe03896bf Mon Sep 17 00:00:00 2001 From: tterrag Date: Thu, 23 May 2019 21:49:39 -0400 Subject: [PATCH] Remove cache eviction for model data, optimize --- .../client/model/ModelDataManager.java | 64 +++++++++---------- 1 file changed, 29 insertions(+), 35 deletions(-) diff --git a/src/main/java/net/minecraftforge/client/model/ModelDataManager.java b/src/main/java/net/minecraftforge/client/model/ModelDataManager.java index 5231b5d22..819c5a275 100644 --- a/src/main/java/net/minecraftforge/client/model/ModelDataManager.java +++ b/src/main/java/net/minecraftforge/client/model/ModelDataManager.java @@ -21,54 +21,43 @@ package net.minecraftforge.client.model; import java.lang.ref.WeakReference; import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; -import javax.annotation.Nonnull; import javax.annotation.Nullable; import com.google.common.base.Preconditions; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; import net.minecraft.client.Minecraft; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; import net.minecraft.world.World; +import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.client.model.data.IModelData; +import net.minecraftforge.event.world.ChunkEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus; +@EventBusSubscriber(modid = "forge", bus = Bus.FORGE, value = Dist.CLIENT) public class ModelDataManager { private static WeakReference currentWorld = new WeakReference<>(null); - private static final Map> needModelDataRefresh = new HashMap<>(); + private static final Map> needModelDataRefresh = new ConcurrentHashMap<>(); - private static final LoadingCache> modelDataCache = CacheBuilder.newBuilder() - .maximumSize(1000) - .concurrencyLevel(5) - .expireAfterAccess(30, TimeUnit.SECONDS) - .build(new CacheLoader>(){ + private static final Map> modelDataCache = new ConcurrentHashMap<>(); - @Override - public Map load(@Nonnull ChunkPos key) - { - return new ConcurrentHashMap<>(); - } - }); - private static void cleanCaches(World world) { if (world != currentWorld.get()) { currentWorld = new WeakReference<>(world); needModelDataRefresh.clear(); - modelDataCache.invalidateAll(); + modelDataCache.clear(); } } @@ -77,25 +66,20 @@ public class ModelDataManager World world = te.getWorld(); Preconditions.checkNotNull(world, "Tile entity world must not be null"); Preconditions.checkArgument(world == Minecraft.getInstance().world, "Cannot request a model data refresh for a world other than the current client world"); - synchronized (needModelDataRefresh) - { - cleanCaches(world); - needModelDataRefresh.computeIfAbsent(new ChunkPos(te.getPos()), $ -> Collections.synchronizedSet(new HashSet<>())) - .add(te.getPos()); - } + + cleanCaches(world); + needModelDataRefresh.computeIfAbsent(new ChunkPos(te.getPos()), $ -> Collections.synchronizedSet(new HashSet<>())) + .add(te.getPos()); } private static void refreshModelData(World world, ChunkPos chunk) - { - Set needUpdate; - synchronized (needModelDataRefresh) - { - cleanCaches(world); - needUpdate = needModelDataRefresh.remove(chunk); - } + { + cleanCaches(world); + Set needUpdate = needModelDataRefresh.remove(chunk); + if (needUpdate != null) { - Map data = modelDataCache.getUnchecked(chunk); + Map data = modelDataCache.computeIfAbsent(chunk, $ -> new ConcurrentHashMap<>()); for (BlockPos pos : needUpdate) { TileEntity toUpdate = world.getTileEntity(pos); @@ -107,6 +91,16 @@ public class ModelDataManager } } + @SubscribeEvent + public static void onChunkUnload(ChunkEvent.Unload event) + { + if (!event.getChunk().getWorldForge().isRemote()) return; + + ChunkPos chunk = event.getChunk().getPos(); + needModelDataRefresh.remove(chunk); + modelDataCache.remove(chunk); + } + public static @Nullable IModelData getModelData(World world, BlockPos pos) { return getModelData(world, new ChunkPos(pos)).get(pos); @@ -115,6 +109,6 @@ public class ModelDataManager public static Map getModelData(World world, ChunkPos pos) { refreshModelData(world, pos); - return modelDataCache.getUnchecked(pos); + return modelDataCache.getOrDefault(pos, Collections.emptyMap()); } }