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 807f700a7..570e38f60 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 @@ -51,13 +51,12 @@ public class CommandDeveloper implements DecreeExecutor { Engine engine = IrisToolbelt.access(world).getEngine(); if(engine != null) { long lastUseSize = engine.getMantle().getLastUseMapMemoryUsage(); - long outputToUnload = engine.getMantle().getToUnload(); Iris.info("-------------------------"); Iris.info(C.DARK_PURPLE + "Engine Status"); Iris.info(C.DARK_PURPLE + "Tectonic Limit: " + C.LIGHT_PURPLE + engine.getMantle().getTectonicLimit()); Iris.info(C.DARK_PURPLE + "Tectonic Plates: " + C.LIGHT_PURPLE + engine.getMantle().getLoadedRegionCount()); - Iris.info(C.DARK_PURPLE + "Tectonic ToUnload: " + C.LIGHT_PURPLE + outputToUnload); + Iris.info(C.DARK_PURPLE + "Tectonic ToUnload: " + C.LIGHT_PURPLE + engine.getMantle().getToUnload()); Iris.info(C.DARK_PURPLE + "Tectonic Unload Duration: " + C.LIGHT_PURPLE + Form.duration((long) engine.getMantle().getTectonicDuration())); Iris.info(C.DARK_PURPLE + "Cache Size: " + C.LIGHT_PURPLE + Form.f(IrisData.cacheSize())); Iris.info(C.DARK_PURPLE + "LastUse Size: " + C.LIGHT_PURPLE + Form.mem(lastUseSize)); diff --git a/core/src/main/java/com/volmit/iris/core/service/DynamicPerformanceSVC.java b/core/src/main/java/com/volmit/iris/core/service/DynamicPerformanceSVC.java new file mode 100644 index 000000000..045fd39c5 --- /dev/null +++ b/core/src/main/java/com/volmit/iris/core/service/DynamicPerformanceSVC.java @@ -0,0 +1,84 @@ +package com.volmit.iris.core.service; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonParser; +import com.volmit.iris.Iris; +import com.volmit.iris.core.IrisSettings; +import com.volmit.iris.core.tools.IrisToolbelt; +import com.volmit.iris.engine.framework.Engine; +import com.volmit.iris.util.SFG.WorldHandlerSFG; +import com.volmit.iris.util.format.C; +import com.volmit.iris.util.mantle.Mantle; +import com.volmit.iris.util.math.M; +import com.volmit.iris.util.misc.getHardware; +import com.volmit.iris.util.plugin.IrisService; +import com.volmit.iris.util.scheduling.Looper; +import org.bukkit.Bukkit; +import org.bukkit.plugin.java.JavaPlugin; + +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.nio.file.*; +import java.util.Comparator; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import static com.volmit.iris.util.mantle.Mantle.*; +import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE; + +public class DynamicPerformanceSVC implements IrisService { + private JavaPlugin plugin; + public Looper ticker; + public Mantle mantle; + public Engine engine; + + @Override + public void onEnable() { + this.plugin = Iris.instance; + if (IrisSettings.get().getPerformance().dynamicPerformanceMode) { + Iris.info("Enabled DynamicPerformance"); + this.startupPerformance(); + this.DynamicPerformance(); + ticker.start(); + } + } + + public void DynamicPerformance(){ + ticker = new Looper() { + @Override + protected long loop() { + try { + + + } catch (Throwable e) { + Iris.reportError(e); + e.printStackTrace(); + return -1; + } + + return 1000; + } + }; + } + public void startupPerformance(){ + if (IrisSettings.get().getPerformance().dynamicPerformanceMode) { + tectonicLimit.set(2); + long t = getHardware.getProcessMemory(); + for (; t > 250; ) { + tectonicLimit.getAndAdd(1); + t = t - 250; + } + //tectonicLimit.set(10); + } + } + + @Override + public void onDisable() { + ticker.interrupt(); + + } +} + 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 bef1cddcf..d7d9ecbd9 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 @@ -293,7 +293,7 @@ public interface EngineMantle extends IObjectPlacer { } default long getToUnload(){ - return getMantle().FakeToUnload.get(); + return Mantle.FakeToUnload.get(); } default double getTectonicLimit(){ return getMantle().tectonicLimit.get(); 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 34d2263d7..7cfdf8274 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 @@ -37,25 +37,22 @@ import com.volmit.iris.util.function.Consumer4; import com.volmit.iris.util.math.M; import com.volmit.iris.util.matter.Matter; import com.volmit.iris.util.matter.MatterSlice; -import com.volmit.iris.util.misc.getHardware; import com.volmit.iris.util.parallel.BurstExecutor; import com.volmit.iris.util.parallel.HyperLock; import com.volmit.iris.util.parallel.MultiBurst; -import com.volmit.iris.util.scheduling.Looper; import lombok.Getter; import org.bukkit.Chunk; -import org.checkerframework.checker.units.qual.A; import java.io.EOFException; import java.io.File; import java.io.IOException; +import java.util.Comparator; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; /** * The mantle can store any type of data slice anywhere and manage regions & IO on it's own. @@ -67,16 +64,12 @@ public class Mantle { private final int worldHeight; private final Map lastUse; @Getter - private final Map loadedRegions; + public static Map loadedRegions; private final HyperLock hyperLock; private final KSet unload; private final AtomicBoolean closed; private final MultiBurst ioBurst; private final AtomicBoolean io; - private final Object gcMonitor = new Object(); - long apm = getHardware.getAvailableProcessMemory(); - private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); - int tectonicLimitBeforeOutMemory; /** * Create a new mantle @@ -404,53 +397,82 @@ public class Mantle { * @param baseIdleDuration the duration */ - public AtomicInteger FakeToUnload = new AtomicInteger(0); - public AtomicDouble adjustedIdleDuration = new AtomicDouble(0); - public AtomicInteger tectonicLimit = new AtomicInteger(30); + public static AtomicInteger FakeToUnload = new AtomicInteger(0); + public static AtomicDouble adjustedIdleDuration = new AtomicDouble(0); + public static AtomicInteger tectonicLimit = new AtomicInteger(30); public synchronized void trim(long baseIdleDuration) { if (closed.get()) { throw new RuntimeException("The Mantle is closed"); } - - if (IrisSettings.get().getPerformance().dynamicPerformanceMode){ - tectonicLimit.set(2); - long t = getHardware.getProcessMemory(); - for (; t > 250;){ - tectonicLimit.getAndAdd(1); - t = t - 250; - } - } - adjustedIdleDuration.set(baseIdleDuration); - if (loadedRegions.size() > tectonicLimit.get()) { - // todo update this correctly and maybe do something when its above a 100% - if (IrisSettings.get().getPerformance().dynamicPerformanceMode) { - int tectonicLimitValue = tectonicLimit.get(); - adjustedIdleDuration.set(Math.max(adjustedIdleDuration.get() - (1000 * (((loadedRegions.size() - tectonicLimitValue) / (double) tectonicLimitValue) * 100) * 0.4), 4000)); + if (loadedRegions != null) { + if (loadedRegions.size() > tectonicLimit.get()) { + // todo update this correctly and maybe do something when its above a 100% + if (IrisSettings.get().getPerformance().dynamicPerformanceMode) { + int tectonicLimitValue = tectonicLimit.get(); + adjustedIdleDuration.set(Math.max(adjustedIdleDuration.get() - (1000 * (((loadedRegions.size() - tectonicLimitValue) / (double) tectonicLimitValue) * 100) * 0.4), 4000)); + } } } io.set(true); try { + Set toUnload; Iris.debug("Trimming Tectonic Plates older than " + Form.duration(adjustedIdleDuration.get(), 0)); - Set toUnload = new HashSet<>(); + toUnload = new HashSet<>(); for (Long i : lastUse.keySet()) { double finalAdjustedIdleDuration = adjustedIdleDuration.get(); + Set finalToUnload1 = toUnload; hyperLock.withLong(i, () -> { if (M.ms() - lastUse.get(i) >= finalAdjustedIdleDuration) { - toUnload.add(i); + finalToUnload1.add(i); FakeToUnload.addAndGet(1); Iris.debug("Tectonic Region added to unload"); } }); } - BurstExecutor burstExecutor = new BurstExecutor(Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()), toUnload.size()); + /* + if (loadedRegions.size() > tectonicLimit.get()) { + AtomicInteger dummyLoadedRegions = new AtomicInteger(loadedRegions.size()); + + for (; dummyLoadedRegions.get() > tectonicLimit.get();) { + try { + long fiveSecondsAgo = M.ms() - 5000; + toUnload = new HashSet<>(); + + Long oldestOverFiveSeconds = lastUse.entrySet().stream() + .filter(e -> e.getValue() < fiveSecondsAgo) + .max(Comparator.comparingLong(Map.Entry::getValue)) + .map(Map.Entry::getKey) + .orElse(null); + + if (oldestOverFiveSeconds != null) { + Set finalToUnload = toUnload; + hyperLock.withLong(oldestOverFiveSeconds, () -> { + if (M.ms() - lastUse.get(oldestOverFiveSeconds) >= adjustedIdleDuration.get()) { + finalToUnload.add(oldestOverFiveSeconds); + FakeToUnload.addAndGet(1); + Iris.debug("Oldest Tectonic Region over 5 seconds idle added to unload"); + dummyLoadedRegions.getAndDecrement(); + } + }); + } + } catch (Exception e) { + + } + } + } + */ + + int numThreads = 1; // Specify the number of threads you want + BurstExecutor burstExecutor = new BurstExecutor(Executors.newFixedThreadPool(numThreads), toUnload.size()); + for (Long i : toUnload) { burstExecutor.queue(() -> { @@ -470,7 +492,6 @@ public class Mantle { }); }); } - burstExecutor.complete(); } finally {