new structure

This commit is contained in:
RePixelatedMC
2023-12-17 17:42:28 +01:00
parent c0fdf23133
commit 5507c35547
5 changed files with 86 additions and 201 deletions
@@ -142,8 +142,6 @@ public class IrisSettings {
public int objectLoaderCacheSize = 4_096; public int objectLoaderCacheSize = 4_096;
public int scriptLoaderCacheSize = 512; public int scriptLoaderCacheSize = 512;
public int tectonicUnloadThreads = -1; // -1 = Disabled and instead use the dynamic method public int tectonicUnloadThreads = -1; // -1 = Disabled and instead use the dynamic method
public boolean AggressiveTectonicUnload = false;
public int AggressiveTectonicThreshold = -1; // -1 = Disabled and instead uses the tectonicLimit
} }
@Data @Data
@@ -63,7 +63,6 @@ public class CommandDeveloper implements DecreeExecutor {
Iris.info(C.DARK_PURPLE + "Tectonic Unload Duration: " + C.LIGHT_PURPLE + Form.duration((long) engine.getMantle().getTectonicDuration())); 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 + "Cache Size: " + C.LIGHT_PURPLE + Form.f(IrisData.cacheSize()));
Iris.info(C.DARK_PURPLE + "LastUse Size: " + C.LIGHT_PURPLE + Form.mem(lastUseSize)); Iris.info(C.DARK_PURPLE + "LastUse Size: " + C.LIGHT_PURPLE + Form.mem(lastUseSize));
Iris.info(C.DARK_PURPLE + "Agressive Unload: " + C.LIGHT_PURPLE + IrisSettings.get().getPerformance().AggressiveTectonicUnload);
Iris.info("-------------------------"); Iris.info("-------------------------");
} else { } else {
Iris.info(C.RED + "Engine is null!"); Iris.info(C.RED + "Engine is null!");
@@ -52,7 +52,7 @@ public class ModesSFG {
try { try {
Thread.sleep(1000); Thread.sleep(1000);
} catch (InterruptedException e) { } catch (InterruptedException e) {
// Handle interruption // no
} }
} }
} }
@@ -13,112 +13,51 @@ import org.bukkit.World;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
import static com.volmit.iris.util.mantle.Mantle.tectonicLimit; import static com.volmit.iris.util.mantle.Mantle.tectonicLimit;
public class IrisEngineSVC implements IrisService { public class IrisEngineSVC implements IrisService {
private JavaPlugin plugin; public Looper trimTicker;
public Looper ticker1; public Looper unloadTicker;
public Looper ticker2;
public Looper engineTicker;
public World selectedWorld;
public List<World> IrisWorlds = new ArrayList<>();
public List<World> corruptedIrisWorlds = new ArrayList<>(); public List<World> corruptedIrisWorlds = new ArrayList<>();
// todo make this work with multiple worlds // todo make this work with multiple worlds
@Override @Override
public void onEnable() { public void onEnable() {
this.plugin = Iris.instance;
tectonicLimit.set(2); tectonicLimit.set(2);
long t = getHardware.getProcessMemory(); long t = getHardware.getProcessMemory();
for (; t > 250; ) { while (t > 250) {
tectonicLimit.getAndAdd(1); tectonicLimit.getAndAdd(1);
t = t - 250; t = t - 250;
} }
tectonicLimit.set(10); // DEBUG CODE tectonicLimit.set(10); // DEBUG CODE
this.IrisEngine(); this.setup();
engineTicker.start(); trimTicker.start();
ticker1.start(); unloadTicker.start();
ticker2.start();
} }
private final AtomicReference<World> selectedWorldRef = new AtomicReference<>(); private void setup() {
trimTicker = new Looper() {
private final Supplier<Engine> supplier = createSupplier();
private Engine engine = supplier.get();
public CompletableFuture<World> initializeAsync() {
return CompletableFuture.supplyAsync(() -> {
World selectedWorld = null;
while (selectedWorld == null) {
synchronized (this) {
IrisWorlds.clear();
for (World w : Bukkit.getServer().getWorlds()) {
if (IrisToolbelt.access(w) != null) {
IrisWorlds.add(w);
}
}
if (!IrisWorlds.isEmpty()) {
Random rand = new Random();
int randomIndex = rand.nextInt(IrisWorlds.size());
selectedWorld = IrisWorlds.get(randomIndex);
}
}
if (selectedWorld == null) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return null;
}
}
}
return selectedWorld;
});
}
public void IrisEngine() {
engineTicker = new Looper() {
@Override @Override
protected long loop() { protected long loop() {
try { try {
World world = selectedWorldRef.get(); if (engine != null) {
PlatformChunkGenerator generator = IrisToolbelt.access(world);
if (generator == null) {
initializeAsync().thenAcceptAsync(foundWorld -> selectedWorldRef.set(foundWorld));
} else {
selectedWorld = world;
}
selectedWorld = Bukkit.getWorld("localmemtest"); // debug code
} catch (Throwable e) {
Iris.reportError(e);
e.printStackTrace();
return -1;
}
return 1000;
}
};
ticker1 = new Looper() {
@Override
protected long loop() {
try {
World world = selectedWorld;
PlatformChunkGenerator generator = IrisToolbelt.access(world);
if (generator != null) {
Engine engine = IrisToolbelt.access(world).getEngine();
if (generator != null && generator.getEngine() != null) {
engine.getMantle().trim(); engine.getMantle().trim();
} else {
Iris.info("something is null 1");
}
} }
engine = supplier.get();
} catch (Throwable e) { } catch (Throwable e) {
Iris.reportError(e); Iris.reportError(e);
e.printStackTrace(); e.printStackTrace();
@@ -129,20 +68,17 @@ public class IrisEngineSVC implements IrisService {
} }
}; };
ticker2 = new Looper() { unloadTicker = new Looper() {
private final Supplier<Engine> supplier = createSupplier();
private Engine engine = supplier.get();
@Override @Override
protected long loop() { protected long loop() {
try { try {
World world = selectedWorld; if (engine != null) {
PlatformChunkGenerator generator = IrisToolbelt.access(world);
if (generator != null) {
Engine engine = IrisToolbelt.access(world).getEngine();
if (generator != null && generator.getEngine() != null) {
engine.getMantle().unloadTectonicPlate(); engine.getMantle().unloadTectonicPlate();
} else {
Iris.info("something is null 2");
}
} }
engine = supplier.get();
} catch (Throwable e) { } catch (Throwable e) {
Iris.reportError(e); Iris.reportError(e);
e.printStackTrace(); e.printStackTrace();
@@ -153,11 +89,30 @@ public class IrisEngineSVC implements IrisService {
}; };
} }
private Supplier<Engine> createSupplier() {
AtomicInteger i = new AtomicInteger();
return () -> {
List<World> worlds = Bukkit.getWorlds();
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);
}
if (generator != null && generator.getEngine() != null) {
return generator.getEngine();
}
}
return null;
};
}
@Override @Override
public void onDisable() { public void onDisable() {
ticker1.interrupt(); trimTicker.interrupt();
ticker2.interrupt(); unloadTicker.interrupt();
engineTicker.interrupt();
} }
} }
@@ -60,17 +60,16 @@ import java.util.concurrent.atomic.AtomicLong;
public class Mantle { public class Mantle {
private final File dataFolder; private final File dataFolder;
@Getter
private final int worldHeight; private final int worldHeight;
private final Map<Long, Long> lastUse; private final Map<Long, Long> lastUse;
@Getter @Getter
private final Map<Long, TectonicPlate> loadedRegions; private final Map<Long, TectonicPlate> loadedRegions;
private final HyperLock hyperLock; private final HyperLock hyperLock;
private final KSet<Long> unload;
private final AtomicBoolean closed; private final AtomicBoolean closed;
private final MultiBurst ioBurst; private final MultiBurst ioBurst;
private final AtomicBoolean ioTrim; private final AtomicBoolean ioTrim;
private final AtomicBoolean ioTectonicUnload; private final AtomicBoolean ioTectonicUnload;
public Looper ticker;
/** /**
* Create a new mantle * Create a new mantle
@@ -87,7 +86,6 @@ public class Mantle {
this.ioTrim = new AtomicBoolean(false); this.ioTrim = new AtomicBoolean(false);
this.ioTectonicUnload = new AtomicBoolean(false); this.ioTectonicUnload = new AtomicBoolean(false);
dataFolder.mkdirs(); dataFolder.mkdirs();
unload = new KSet<>();
loadedRegions = new KMap<>(); loadedRegions = new KMap<>();
lastUse = new KMap<>(); lastUse = new KMap<>();
ioBurst = MultiBurst.burst; ioBurst = MultiBurst.burst;
@@ -416,11 +414,6 @@ public class Mantle {
throw new RuntimeException("The Mantle is closed"); throw new RuntimeException("The Mantle is closed");
} }
Iris.debug(C.BLUE + "TECTONIC TRIM HAS RUN"); Iris.debug(C.BLUE + "TECTONIC TRIM HAS RUN");
if (IrisSettings.get().getPerformance().getAggressiveTectonicThreshold() == -1) {
forceAggressiveThreshold.set(tectonicLimit.get());
} else {
forceAggressiveThreshold.set(IrisSettings.get().getPerformance().getAggressiveTectonicThreshold());
}
adjustedIdleDuration.set(baseIdleDuration); adjustedIdleDuration.set(baseIdleDuration);
@@ -448,65 +441,14 @@ public class Mantle {
} }
} }
if (IrisSettings.get().getPerformance().AggressiveTectonicUnload
&& loadedRegions.size() > forceAggressiveThreshold.get()) {
AtomicInteger regionCountToRemove = new AtomicInteger(0);
if (loadedRegions.size() > tectonicLimit.get()) {
regionCountToRemove.set(loadedRegions.size() - tectonicLimit.get());
}
while (regionCountToRemove.get() > 0) {
Long[] oldestKey = {null};
long[] oldestAge = {Long.MIN_VALUE};
for (Long key : lastUse.keySet()) {
hyperLock.withLong(key, () -> {
if (!toUnload.contains(key)) {
long age = M.ms() - lastUse.get(key);
if (age > oldestAge[0]) {
oldestAge[0] = age;
oldestKey[0] = key;
}
}
});
}
if (oldestKey[0] != null) {
Long finalOldestKey = oldestKey[0];
hyperLock.withLong(finalOldestKey, () -> {
toUnload.add(finalOldestKey);
Iris.debug("Oldest Tectonic Region " + finalOldestKey + " added to unload");
regionCountToRemove.getAndDecrement();
});
}
}
}
} finally { } finally {
ioTrim.set(false); ioTrim.set(false);
} }
} }
public synchronized void unloadTectonicPlate() { public void unloadTectonicPlate() {
long time = System.currentTimeMillis();
try { try {
Iris.debug(C.DARK_BLUE + "TECTONIC UNLOAD HAS RUN"); for (Long id : new ArrayList<>(toUnload)) {
int threadCount = 1;
ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
List<Long> toUnloadList;
synchronized (toUnload) {
toUnloadList = new ArrayList<>(toUnload);
}
int chunkSize = (int) Math.ceil(toUnloadList.size() / (double) threadCount);
for (int i = 0; i < threadCount; i++) {
int start = i * chunkSize;
int end = Math.min(start + chunkSize, toUnloadList.size());
List<Long> sublist = toUnloadList.subList(start, end);
executorService.submit(() -> {
for (Long id : sublist) {
hyperLock.withLong(id, () -> { hyperLock.withLong(id, () -> {
TectonicPlate m = loadedRegions.get(id); TectonicPlate m = loadedRegions.get(id);
if (m != null) { if (m != null) {
@@ -522,18 +464,13 @@ public class Mantle {
} }
}); });
} }
});
}
executorService.shutdown();
executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
ioTectonicUnload.set(true); ioTectonicUnload.set(true);
} }
/** /**
* This retreives a future of the Tectonic Plate at the given coordinates. * This retreives a future of the Tectonic Plate at the given coordinates.
* All methods accessing tectonic plates should go through this method * All methods accessing tectonic plates should go through this method
@@ -639,10 +576,6 @@ public class Mantle {
} }
public int getWorldHeight() {
return worldHeight;
}
public MantleChunk getChunk(Chunk e) { public MantleChunk getChunk(Chunk e) {
return getChunk(e.getX(), e.getZ()); return getChunk(e.getX(), e.getZ());
} }