From df9114d7b09f6278b1d9938df915b724c62fb563 Mon Sep 17 00:00:00 2001 From: Daniel Mills Date: Sat, 17 Jul 2021 00:33:32 -0400 Subject: [PATCH] Parallax Feature Performance Caching --- .../iris/engine/IrisEngineParallax.java | 15 ++++ .../iris/engine/framework/EngineCompound.java | 4 +- .../framework/EngineParallaxManager.java | 78 +++++++++++++------ .../engine/parallax/ParallaxChunkMeta.java | 5 +- 4 files changed, 74 insertions(+), 28 deletions(-) diff --git a/src/main/java/com/volmit/iris/engine/IrisEngineParallax.java b/src/main/java/com/volmit/iris/engine/IrisEngineParallax.java index f5ce791ca..3c91afc1f 100644 --- a/src/main/java/com/volmit/iris/engine/IrisEngineParallax.java +++ b/src/main/java/com/volmit/iris/engine/IrisEngineParallax.java @@ -18,8 +18,13 @@ package com.volmit.iris.engine; +import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap; import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.engine.framework.EngineParallaxManager; +import com.volmit.iris.engine.object.IrisFeaturePositional; +import com.volmit.iris.engine.stream.utility.CachedStream2D; +import com.volmit.iris.util.collection.KList; +import com.volmit.iris.util.scheduling.IrisLock; import lombok.Getter; public class IrisEngineParallax implements EngineParallaxManager { @@ -29,6 +34,16 @@ public class IrisEngineParallax implements EngineParallaxManager { @Getter private final int parallaxSize; + @Getter + private final IrisLock featureLock = new IrisLock("Feature"); + + @Getter + private final ConcurrentLinkedHashMap> featureCache = new ConcurrentLinkedHashMap.Builder>() + .initialCapacity(1024) + .maximumWeightedCapacity(1024) + .concurrencyLevel(32) + .build(); + public IrisEngineParallax(Engine engine) { this.engine = engine; parallaxSize = computeParallaxSize(); diff --git a/src/main/java/com/volmit/iris/engine/framework/EngineCompound.java b/src/main/java/com/volmit/iris/engine/framework/EngineCompound.java index 1f251c4f3..cff9a2dd9 100644 --- a/src/main/java/com/volmit/iris/engine/framework/EngineCompound.java +++ b/src/main/java/com/volmit/iris/engine/framework/EngineCompound.java @@ -20,7 +20,7 @@ package com.volmit.iris.engine.framework; import com.volmit.iris.Iris; import com.volmit.iris.core.IrisDataManager; -import com.volmit.iris.engine.actuator.IrisTerrainActuator; +import com.volmit.iris.engine.actuator.IrisTerrainNormalActuator; import com.volmit.iris.engine.data.DataProvider; import com.volmit.iris.engine.hunk.Hunk; import com.volmit.iris.engine.object.IrisBiome; @@ -158,7 +158,7 @@ public interface EngineCompound extends Listener, Hotloadable, DataProvider { Engine e = getEngine(i); if (e.getDimension().isBedrock()) { - int m = ((IrisTerrainActuator) e.getFramework().getTerrainActuator()).getLastBedrock(); + int m = ((IrisTerrainNormalActuator) e.getFramework().getTerrainActuator()).getLastBedrock(); if (f > m) { f = m; diff --git a/src/main/java/com/volmit/iris/engine/framework/EngineParallaxManager.java b/src/main/java/com/volmit/iris/engine/framework/EngineParallaxManager.java index 5a5bb0fe3..f1a60eb7b 100644 --- a/src/main/java/com/volmit/iris/engine/framework/EngineParallaxManager.java +++ b/src/main/java/com/volmit/iris/engine/framework/EngineParallaxManager.java @@ -18,6 +18,7 @@ package com.volmit.iris.engine.framework; +import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap; import com.volmit.iris.Iris; import com.volmit.iris.core.IrisDataManager; import com.volmit.iris.engine.IrisComplex; @@ -40,6 +41,7 @@ import com.volmit.iris.util.collection.KSet; import com.volmit.iris.util.format.Form; import com.volmit.iris.util.function.Consumer4; import com.volmit.iris.util.math.RNG; +import com.volmit.iris.util.scheduling.IrisLock; import com.volmit.iris.util.scheduling.J; import com.volmit.iris.util.scheduling.PrecisionStopwatch; import org.bukkit.Chunk; @@ -192,41 +194,69 @@ public interface EngineParallaxManager extends DataProvider, IObjectPlacer { } } + ConcurrentLinkedHashMap> getFeatureCache(); + + IrisLock getFeatureLock(); + default void forEachFeature(double x, double z, Consumer f) { - for (IrisFeaturePositional i : getEngine().getDimension().getSpecificFeatures()) { - if (i.shouldFilter(x, z)) { - f.accept(i); + long key = Cache.key(((int)x)>>4, ((int)z) >> 4); + + for(IrisFeaturePositional ipf : getFeatureCache().compute(key, (ke, v) -> { + if(v != null) + { + return v; } - } - int s = (int) Math.ceil(getParallaxSize() / 2D); - int i, j; - int cx = (int) x >> 4; - int cz = (int) z >> 4; + getFeatureLock().lock(); + KList pos = new KList<>(); - for (i = -s; i <= s; i++) { - for (j = -s; j <= s; j++) { - ParallaxChunkMeta m = getParallaxAccess().getMetaR(i + cx, j + cz); - - try { - synchronized (m.getFeatures()) { - for (IrisFeaturePositional k : m.getFeatures()) { - if (k.shouldFilter(x, z)) { - f.accept(k); - } - } - } - } catch (Throwable e) { - Iris.reportError(e); - e.printStackTrace(); - Iris.warn("Failed to read positional features in chunk " + (i + cx) + " " + (j + cz) + "(" + e.getClass().getSimpleName() + ")"); + for (IrisFeaturePositional i : getEngine().getDimension().getSpecificFeatures()) { + if (i.shouldFilter(x, z)) { + pos.add(i); } } + + int s = (int) Math.ceil(getParallaxSize() / 2D); + int i, j; + int cx = (int) x >> 4; + int cz = (int) z >> 4; + + for (i = -s; i <= s; i++) { + for (j = -s; j <= s; j++) { + ParallaxChunkMeta m = getParallaxAccess().getMetaR(i + cx, j + cz); + + try { + synchronized (m.getFeatures()) + { + for (IrisFeaturePositional k : m.getFeatures()) { + if (k.shouldFilter(x, z)) { + pos.add(k); + } + } + } + } catch (Throwable e) { + Iris.reportError(e); + e.printStackTrace(); + Iris.warn("Failed to read positional features in chunk " + (i + cx) + " " + (j + cz) + "(" + e.getClass().getSimpleName() + ")"); + } + } + } + getFeatureLock().unlock(); + + return pos; + })) + { + f.accept(ipf); } } @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") default void generateParallaxArea(int x, int z) { + if(!getEngine().getDimension().isPlaceObjects()) + { + return; + } + try { PrecisionStopwatch p = PrecisionStopwatch.start(); diff --git a/src/main/java/com/volmit/iris/engine/parallax/ParallaxChunkMeta.java b/src/main/java/com/volmit/iris/engine/parallax/ParallaxChunkMeta.java index 89865e50d..428b1d99e 100644 --- a/src/main/java/com/volmit/iris/engine/parallax/ParallaxChunkMeta.java +++ b/src/main/java/com/volmit/iris/engine/parallax/ParallaxChunkMeta.java @@ -22,6 +22,7 @@ import com.google.gson.Gson; import com.volmit.iris.engine.hunk.io.HunkIOAdapter; import com.volmit.iris.engine.hunk.io.PaletteHunkIOAdapter; import com.volmit.iris.engine.object.IrisFeaturePositional; +import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.oldnbt.CompoundTag; import lombok.AllArgsConstructor; import lombok.Data; @@ -56,9 +57,9 @@ public class ParallaxChunkMeta { private int maxObject = -1; private int minObject = -1; private int count; - private CopyOnWriteArrayList features; + private KList features; public ParallaxChunkMeta() { - this(false, false, false, false, false, false, -1, -1, 0, new CopyOnWriteArrayList<>()); + this(false, false, false, false, false, false, -1, -1, 0, new KList<>()); } }