From 63606d7c58955193c528535aeaef4b58b52a5984 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Sat, 14 Sep 2024 21:07:20 +0100 Subject: [PATCH] It's ugly but it stops OOM --- .../impl/fawe/v1_21_R1/PaperweightGetBlocks.java | 12 +++++++++++- .../main/java/com/fastasyncworldedit/core/Fawe.java | 6 ++++++ .../fastasyncworldedit/core/queue/IQueueExtent.java | 9 +-------- .../com/fastasyncworldedit/core/util/MemUtil.java | 12 ++++++++++++ 4 files changed, 30 insertions(+), 9 deletions(-) diff --git a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightGetBlocks.java index 5c4e37bb4c..d8ce0c2b1e 100644 --- a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightGetBlocks.java +++ b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightGetBlocks.java @@ -17,6 +17,7 @@ import com.fastasyncworldedit.core.queue.implementation.QueueHandler; import com.fastasyncworldedit.core.queue.implementation.blocks.CharGetBlocks; import com.fastasyncworldedit.core.util.MathMan; +import com.fastasyncworldedit.core.util.MemUtil; import com.fastasyncworldedit.core.util.NbtUtils; import com.fastasyncworldedit.core.util.collection.AdaptedMap; import com.sk89q.worldedit.bukkit.BukkitAdapter; @@ -430,7 +431,7 @@ public CompletableFuture ensureLoaded(ServerLevel nmsWorld, int chun } @Override - @SuppressWarnings("rawtypes") + @SuppressWarnings({"rawtypes", "unchecked"}) public synchronized > T call(IQueueExtent owner, IChunkSet set, Runnable finalizer) { if (!callLock.isHeldByCurrentThread()) { throw new IllegalStateException("Attempted to call chunk GET but chunk was not call-locked."); @@ -439,6 +440,15 @@ public synchronized > T call(IQueueExtent final ServerLevel nmsWorld = serverLevel; CompletableFuture nmsChunkFuture = ensureLoaded(nmsWorld, chunkX, chunkZ); LevelChunk chunk = nmsChunkFuture.getNow(null); + if (chunk == null && MemUtil.shouldBeginSlow()) { + try { + chunk = nmsChunkFuture.get(); // "Artificially" slow FAWE down if memory low as performing the + } catch (InterruptedException | ExecutionException e) { + LOGGER.error("Could not get chunk at {},{} whilst low memory", chunkX, chunkZ, e); + throw new FaweException( + TextComponent.of("Could not get chunk at " + chunkX + "," + chunkZ + " whilst low memory: " + e.getMessage())); + } + } // Run immediately if possible if (chunk != null) { return internalCall(set, finalizer, chunk, nmsWorld); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java index dac6fe9d63..74e1bf9459 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java @@ -138,6 +138,7 @@ private Fawe(final IFawe implementation) { } catch (Throwable ignored) { } }, 0); + TaskManager.taskManager().repeatAsync(() -> MemUtil.checkAndSetApproachingLimit(), 1); TaskManager.taskManager().repeat(timer, 1); @@ -417,11 +418,16 @@ private void setupMemoryListener() { final NotificationEmitter ne = (NotificationEmitter) memBean; ne.addNotificationListener((notification, handback) -> { + LOGGER.info("Notification"); final long heapSize = Runtime.getRuntime().totalMemory(); final long heapMaxSize = Runtime.getRuntime().maxMemory(); if (heapSize < heapMaxSize) { return; } + LOGGER.info("NNNNNNNNNNNNNNNNNNNNNNNNNNNN"); + LOGGER.info("NNNNNNNNNNNNNNNNNNNNNNNNNNNN"); + LOGGER.info("NNNNNNNNNNNNNNNNNNNNNNNNNNNN"); + LOGGER.info("JJJJJJJJJJJJJJJJJJJJJJJJJJJJ"); MemUtil.memoryLimitedTask(); }, null, null); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IQueueExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IQueueExtent.java index ba27c73862..bcb4152346 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IQueueExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IQueueExtent.java @@ -2,9 +2,6 @@ import com.fastasyncworldedit.core.extent.filter.block.ChunkFilterBlock; import com.fastasyncworldedit.core.extent.processor.IBatchProcessorHolder; -import com.fastasyncworldedit.core.internal.simd.SimdSupport; -import com.fastasyncworldedit.core.internal.simd.VectorizedCharFilterBlock; -import com.fastasyncworldedit.core.internal.simd.VectorizedFilter; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.math.BlockVector2; @@ -157,11 +154,7 @@ default ChunkFilterBlock apply( if (newChunk != null) { chunk = newChunk; if (block == null) { - if (SimdSupport.useVectorApi() && filter instanceof VectorizedFilter) { - block = new VectorizedCharFilterBlock(this); - } else { - block = this.createFilterBlock(); - } + block = this.createFilterBlock(); } block.initChunk(chunkX, chunkZ); chunk.filterBlocks(filter, block, region, full); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/MemUtil.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/MemUtil.java index 7760663ea2..f72fe92f0c 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/MemUtil.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/MemUtil.java @@ -9,6 +9,7 @@ public class MemUtil { private static final AtomicBoolean memory = new AtomicBoolean(false); + private static final AtomicBoolean slower = new AtomicBoolean(false); public static boolean isMemoryFree() { return !memory.get(); @@ -28,6 +29,10 @@ public static boolean isMemoryLimitedSlow() { return false; } + public static boolean shouldBeginSlow() { + return slower.get(); + } + public static long getUsedBytes() { return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); } @@ -51,6 +56,13 @@ public static int calculateMemory() { return size; } + public static void checkAndSetApproachingLimit() { + final long heapFreeSize = Runtime.getRuntime().freeMemory(); + final long heapMaxSize = Runtime.getRuntime().maxMemory(); + final int size = (int) ((heapFreeSize * 100) / heapMaxSize); + slower.set(size > 80); + } + private static final Queue memoryLimitedTasks = new ConcurrentLinkedQueue<>(); private static final Queue memoryPlentifulTasks = new ConcurrentLinkedQueue<>();