diff --git a/core/src/main/java/com/volmit/iris/core/commands/CommandDeveloper.java b/core/src/main/java/com/volmit/iris/core/commands/CommandDeveloper.java index 018329aff..2d2286fa6 100644 --- a/core/src/main/java/com/volmit/iris/core/commands/CommandDeveloper.java +++ b/core/src/main/java/com/volmit/iris/core/commands/CommandDeveloper.java @@ -21,6 +21,7 @@ package com.volmit.iris.core.commands; import com.volmit.iris.Iris; import com.volmit.iris.core.IrisSettings; import com.volmit.iris.core.loader.IrisData; +import com.volmit.iris.core.service.IrisEngineSVC; import com.volmit.iris.core.tools.IrisToolbelt; import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.engine.mantle.EngineMantle; @@ -56,7 +57,7 @@ public class CommandDeveloper implements DecreeExecutor { Iris.info("-------------------------"); Iris.info(C.DARK_PURPLE + "Engine Status"); Iris.info(C.DARK_PURPLE + "Tectonic Threads: " + C.LIGHT_PURPLE + engine.getMantle().getDynamicThreads()); - Iris.info(C.DARK_PURPLE + "Tectonic Limit: " + C.LIGHT_PURPLE + engine.getMantle().getTectonicLimit()); + Iris.info(C.DARK_PURPLE + "Tectonic Limit: " + C.LIGHT_PURPLE + IrisEngineSVC.getTectonicLimit()); Iris.info(C.DARK_PURPLE + "Tectonic Loaded Plates: " + C.LIGHT_PURPLE + engine.getMantle().getLoadedRegionCount()); Iris.info(C.DARK_PURPLE + "Tectonic Plates: " + C.LIGHT_PURPLE + engine.getMantle().getNotClearedLoadedRegions()); Iris.info(C.DARK_PURPLE + "Tectonic ToUnload: " + C.LIGHT_PURPLE + engine.getMantle().getToUnload()); diff --git a/core/src/main/java/com/volmit/iris/core/pregenerator/IrisPregenerator.java b/core/src/main/java/com/volmit/iris/core/pregenerator/IrisPregenerator.java index 513600a95..11128d04a 100644 --- a/core/src/main/java/com/volmit/iris/core/pregenerator/IrisPregenerator.java +++ b/core/src/main/java/com/volmit/iris/core/pregenerator/IrisPregenerator.java @@ -167,7 +167,7 @@ public class IrisPregenerator { generator.close(); ticker.interrupt(); listener.onClose(); - getMantle().trim(0); + getMantle().trim(0, 0); } private void visitRegion(int x, int z, boolean regions) { diff --git a/core/src/main/java/com/volmit/iris/core/service/IrisEngineSVC.java b/core/src/main/java/com/volmit/iris/core/service/IrisEngineSVC.java index 93a306887..6dcca86fb 100644 --- a/core/src/main/java/com/volmit/iris/core/service/IrisEngineSVC.java +++ b/core/src/main/java/com/volmit/iris/core/service/IrisEngineSVC.java @@ -4,30 +4,24 @@ import com.volmit.iris.Iris; import com.volmit.iris.core.tools.IrisToolbelt; import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.engine.platform.PlatformChunkGenerator; +import com.volmit.iris.util.collection.KMap; import com.volmit.iris.util.misc.getHardware; import com.volmit.iris.util.plugin.IrisService; -import com.volmit.iris.util.scheduling.J; import com.volmit.iris.util.scheduling.Looper; import org.bukkit.Bukkit; import org.bukkit.World; -import org.bukkit.plugin.java.JavaPlugin; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; -import java.util.Random; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; import java.util.function.Supplier; -import static com.volmit.iris.util.mantle.Mantle.tectonicLimit; - public class IrisEngineSVC implements IrisService { - public Looper trimTicker; - public Looper unloadTicker; + private static final AtomicInteger tectonicLimit = new AtomicInteger(30); + private final KMap cache = new KMap<>(); + private Looper cacheTicker; + private Looper trimTicker; + private Looper unloadTicker; public List corruptedIrisWorlds = new ArrayList<>(); // todo make this work with multiple worlds @@ -42,49 +36,73 @@ public class IrisEngineSVC implements IrisService { } tectonicLimit.set(10); // DEBUG CODE this.setup(); + cacheTicker.start(); trimTicker.start(); unloadTicker.start(); } - private void setup() { - trimTicker = new Looper() { - private final Supplier supplier = createSupplier(); - private Engine engine = supplier.get(); + public static int getTectonicLimit() { + return tectonicLimit.get(); + } + private void setup() { + cacheTicker = new Looper() { @Override protected long loop() { - try { - if (engine != null) { - engine.getMantle().trim(); + long now = System.currentTimeMillis(); + for (Engine key : cache.keySet()) { + long last = cache.get(key); + if (now - last > 600000) { // 10 minutes + cache.remove(key); + } + } + return 1000; + } + }; + trimTicker = new Looper() { + private final Supplier supplier = createSupplier(); + @Override + protected long loop() { + long start = System.currentTimeMillis(); + try { + Engine engine = supplier.get(); + if (engine != null) { + engine.getMantle().trim(tectonicLimit.get() / cache.size()); } - engine = supplier.get(); } catch (Throwable e) { Iris.reportError(e); - e.printStackTrace(); return -1; } - return 1000; + int size = cache.size(); + long time = (size > 0 ? 1000/size : 1000) - (System.currentTimeMillis() - start); + if (time <= 0) + return 0; + return time; } }; unloadTicker = new Looper() { private final Supplier supplier = createSupplier(); - private Engine engine = supplier.get(); @Override protected long loop() { + long start = System.currentTimeMillis(); try { + Engine engine = supplier.get(); if (engine != null) { engine.getMantle().unloadTectonicPlate(); } - engine = supplier.get(); } catch (Throwable e) { Iris.reportError(e); - e.printStackTrace(); return -1; } - return 1000; + + int size = cache.size(); + long time = (size > 0 ? 1000/size : 1000) - (System.currentTimeMillis() - start); + if (time <= 0) + return 0; + return time; } }; } @@ -96,15 +114,23 @@ public class IrisEngineSVC implements IrisService { if (i.get() >= worlds.size()) { i.set(0); } - for (int j = 0; j < worlds.size(); j++) { - PlatformChunkGenerator generator = IrisToolbelt.access(worlds.get(i.getAndIncrement())); - if (i.get() >= worlds.size()) { - i.set(0); - } + try { + for (int j = 0; j < worlds.size(); j++) { + PlatformChunkGenerator generator = IrisToolbelt.access(worlds.get(i.getAndIncrement())); + if (i.get() >= worlds.size()) { + i.set(0); + } - if (generator != null && generator.getEngine() != null) { - return generator.getEngine(); + if (generator != null) { + Engine engine = generator.getEngine(); + if (engine != null) { + cache.put(engine, System.currentTimeMillis()); + return engine; + } + } } + } catch (Throwable e) { + Iris.reportError(e); } return null; }; @@ -112,7 +138,9 @@ public class IrisEngineSVC implements IrisService { @Override public void onDisable() { + cacheTicker.interrupt(); trimTicker.interrupt(); unloadTicker.interrupt(); + cache.clear(); } } diff --git a/core/src/main/java/com/volmit/iris/engine/framework/Engine.java b/core/src/main/java/com/volmit/iris/engine/framework/Engine.java index 11249b1f6..31bba630e 100644 --- a/core/src/main/java/com/volmit/iris/engine/framework/Engine.java +++ b/core/src/main/java/com/volmit/iris/engine/framework/Engine.java @@ -523,8 +523,9 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat return getTarget().getBurster(); } + @Deprecated default void clean() { - burst().lazy(() -> getMantle().trim()); + burst().lazy(() -> getMantle().trim(10)); } @BlockCoordinates diff --git a/core/src/main/java/com/volmit/iris/engine/mantle/EngineMantle.java b/core/src/main/java/com/volmit/iris/engine/mantle/EngineMantle.java index c6d234c2e..8fee0baaf 100644 --- a/core/src/main/java/com/volmit/iris/engine/mantle/EngineMantle.java +++ b/core/src/main/java/com/volmit/iris/engine/mantle/EngineMantle.java @@ -143,8 +143,8 @@ public interface EngineMantle extends IObjectPlacer { return getEngine().getDimension().isDebugSmartBore(); } - default void trim(long dur) { - getMantle().trim(dur); + default void trim(long dur, int limit) { + getMantle().trim(dur, limit); } default IrisData getData() { @@ -175,8 +175,8 @@ public interface EngineMantle extends IObjectPlacer { } - default void trim() { - getMantle().trim(TimeUnit.SECONDS.toMillis(IrisSettings.get().getPerformance().getMantleKeepAlive())); + default void trim(int limit) { + getMantle().trim(TimeUnit.SECONDS.toMillis(IrisSettings.get().getPerformance().getMantleKeepAlive()), limit); } default void unloadTectonicPlate(){ getMantle().unloadTectonicPlate(); @@ -301,9 +301,6 @@ public interface EngineMantle extends IObjectPlacer { default long getDynamicThreads(){ return getMantle().getDynamicThreads().get(); } - default double getTectonicLimit(){ - return Mantle.tectonicLimit.get(); - } default long getNotClearedLoadedRegions(){ return getMantle().getLoadedRegions().size() - getMantle().getToUnload().size(); } diff --git a/core/src/main/java/com/volmit/iris/util/mantle/Mantle.java b/core/src/main/java/com/volmit/iris/util/mantle/Mantle.java index 4a8d8b07d..a52b8dbb9 100644 --- a/core/src/main/java/com/volmit/iris/util/mantle/Mantle.java +++ b/core/src/main/java/com/volmit/iris/util/mantle/Mantle.java @@ -392,7 +392,6 @@ public class Mantle { @Getter private final AtomicDouble adjustedIdleDuration = new AtomicDouble(0); - public static final AtomicInteger tectonicLimit = new AtomicInteger(30); @Getter private final AtomicInteger dynamicThreads = new AtomicInteger(4); @Getter @@ -401,7 +400,6 @@ public class Mantle { private final AtomicLong oldestTectonicPlate = new AtomicLong(0); @Getter public final Set toUnload = new HashSet<>(); - private int g = 0; /** * Save & unload regions that have not been used for more than the @@ -409,7 +407,7 @@ public class Mantle { * * @param baseIdleDuration the duration */ - public synchronized void trim(long baseIdleDuration) { + public synchronized void trim(long baseIdleDuration, int tectonicLimit) { if (closed.get()) { throw new RuntimeException("The Mantle is closed"); } @@ -418,10 +416,9 @@ public class Mantle { adjustedIdleDuration.set(baseIdleDuration); if (loadedRegions != null) { - if (loadedRegions.size() > tectonicLimit.get()) { + if (loadedRegions.size() > tectonicLimit) { // todo update this correctly and maybe do something when its above a 100% - int tectonicLimitValue = tectonicLimit.get(); - adjustedIdleDuration.set(Math.max(adjustedIdleDuration.get() - (1000 * (((loadedRegions.size() - tectonicLimitValue) / (double) tectonicLimitValue) * 100) * 0.4), 4000)); + adjustedIdleDuration.set(Math.max(adjustedIdleDuration.get() - (1000 * (((loadedRegions.size() - tectonicLimit) / (double) tectonicLimit) * 100) * 0.4), 4000)); } }