9
0
mirror of https://github.com/BX-Team/DivineMC.git synced 2025-12-19 14:59:25 +00:00

add back chunk system algorithms

This commit is contained in:
NONPLAYT
2025-10-29 01:33:11 +03:00
parent 8ab1873995
commit c33fb58555
4 changed files with 188 additions and 1 deletions

View File

@@ -72,7 +72,7 @@
}
}
val log4jPlugins = sourceSets.create("log4jPlugins") {
@@ -154,10 +_,22 @@
@@ -154,10 +_,23 @@
}
dependencies {
@@ -88,6 +88,7 @@
+ implementation("org.lz4:lz4-java:1.8.0")
+ implementation("net.openhft:zero-allocation-hashing:0.16")
+ implementation("org.agrona:agrona:2.2.4")
+ implementation("net.objecthunter:exp4j:0.4.8")
+ // DivineMC end - Dependencies
+
implementation("ca.spottedleaf:concurrentutil:0.0.5")

View File

@@ -0,0 +1,60 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
Date: Wed, 29 Oct 2025 01:31:51 +0300
Subject: [PATCH] Implement chunk system algorithm
This patch adds configurable chunk system algorithms for determining
worker thread allocation for chunk loading and generation.
diff --git a/src/main/java/ca/spottedleaf/moonrise/common/util/MoonriseCommon.java b/src/main/java/ca/spottedleaf/moonrise/common/util/MoonriseCommon.java
index 9a1fbd88e56f8dd01368a0a5e74cfa8c54965d7f..0a21222c77b84601841e1750daf3eb0865d99b67 100644
--- a/src/main/java/ca/spottedleaf/moonrise/common/util/MoonriseCommon.java
+++ b/src/main/java/ca/spottedleaf/moonrise/common/util/MoonriseCommon.java
@@ -34,27 +34,17 @@ public final class MoonriseCommon {
public static final BalancedPrioritisedThreadPool.OrderedStreamGroup CLIENT_GROUP = MoonriseCommon.WORKER_POOL.createOrderedStreamGroup();
public static final BalancedPrioritisedThreadPool.OrderedStreamGroup SERVER_GROUP = MoonriseCommon.WORKER_POOL.createOrderedStreamGroup();
- public static void adjustWorkerThreads(final int configWorkerThreads, final int configIoThreads) {
- int defaultWorkerThreads = Runtime.getRuntime().availableProcessors() / 2;
- if (defaultWorkerThreads <= 4) {
- defaultWorkerThreads = defaultWorkerThreads <= 3 ? 1 : 2;
- } else {
- defaultWorkerThreads = defaultWorkerThreads / 2;
- }
- defaultWorkerThreads = Integer.getInteger(PlatformHooks.get().getBrand() + ".WorkerThreadCount", Integer.valueOf(defaultWorkerThreads));
-
- int workerThreads = configWorkerThreads;
-
- if (workerThreads <= 0) {
- workerThreads = defaultWorkerThreads;
- }
-
- final int ioThreads = Math.max(1, configIoThreads);
+ public static void init(final int configWorkerThreads, final int configIoThreads) {
+ // DivineMC start - Implement chunk system algorithm
+ org.bxteam.divinemc.chunk.ChunkSystemAlgorithm algorithm = org.bxteam.divinemc.config.DivineConfig.PerformanceCategory.chunkWorkerAlgorithm;
+ int workerThreads = algorithm.evalWorkers(configWorkerThreads, configIoThreads);
+ int ioThreads = algorithm.evalIO(configWorkerThreads, configIoThreads);
+ // DivineMC end - Implement chunk system algorithm
WORKER_POOL.adjustThreadCount(workerThreads);
IO_POOL.adjustThreadCount(ioThreads);
- LOGGER.info(PlatformHooks.get().getBrand() + " is using " + workerThreads + " worker threads, " + ioThreads + " I/O threads");
+ LOGGER.info("{} is using {} worker threads, {} I/O threads", PlatformHooks.get().getBrand(), workerThreads, ioThreads); // DivineMC - Implement chunk system algorithm - better logging
}
public static final long IO_QUEUE_HOLD_TIME = (long)(25.0e6); // 25ms
diff --git a/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java b/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java
index 6c23b24477dd24ed43932d0c5ae5d97f80d968f6..982ffe9c9ec54242cdf7ee6dca42e9f815666260 100644
--- a/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java
+++ b/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java
@@ -227,7 +227,7 @@ public class GlobalConfiguration extends ConfigurationPart {
@PostProcess
private void postProcess() {
- ca.spottedleaf.moonrise.common.util.MoonriseCommon.adjustWorkerThreads(this.workerThreads, this.ioThreads);
+ ca.spottedleaf.moonrise.common.util.MoonriseCommon.init(this.workerThreads, this.ioThreads); // DivineMC - Implement chunk system algorithm
}
}

View File

@@ -0,0 +1,117 @@
package org.bxteam.divinemc.chunk;
import ca.spottedleaf.moonrise.common.PlatformHooks;
import io.netty.util.internal.PlatformDependent;
import net.objecthunter.exp4j.ExpressionBuilder;
import net.objecthunter.exp4j.function.Function;
import org.jetbrains.annotations.NotNull;
import oshi.util.tuples.Pair;
import java.util.function.BiFunction;
public enum ChunkSystemAlgorithm {
MOONRISE((configWorkerThreads, configIoThreads) -> {
int defaultWorkerThreads = Runtime.getRuntime().availableProcessors() / 2;
if (defaultWorkerThreads <= 4) {
defaultWorkerThreads = defaultWorkerThreads <= 3 ? 1 : 2;
} else {
defaultWorkerThreads = defaultWorkerThreads / 2;
}
defaultWorkerThreads = Integer.getInteger(PlatformHooks.get().getBrand() + ".WorkerThreadCount", Integer.valueOf(defaultWorkerThreads));
int workerThreads = configWorkerThreads;
if (workerThreads <= 0) {
workerThreads = defaultWorkerThreads;
}
final int ioThreads = Math.max(1, configIoThreads);
return new Pair<>(workerThreads, ioThreads);
}),
C2ME_NEW((configWorkerThreads, configIoThreads) -> {
String expression = """
max(
1,
min(
if( is_windows,
(cpus / 1.6),
(cpus / 1.3)
) - if(is_client, 1, 0),
( ( mem_gb - (if(is_client, 1.0, 0.5)) ) / 0.6 )
)
)
\040""";
int eval = configWorkerThreads <= 0 ? tryEvaluateExpression(expression) : configWorkerThreads;
return new Pair<>(eval, Math.max(1, configIoThreads));
}),
C2ME((configWorkerThreads, configIoThreads) -> {
String expression = """
max(
1,
min(
if( is_windows,
(cpus / 1.6 - 2),
(cpus / 1.2 - 2)
) - if(is_client, 2, 0),
if( is_j9vm,
( ( mem_gb - (if(is_client, 0.6, 0.2)) ) / 0.4 ),
( ( mem_gb - (if(is_client, 1.2, 0.6)) ) / 0.6 )
)
)
)
\040""";
int eval = configWorkerThreads <= 0 ? tryEvaluateExpression(expression) : configWorkerThreads;
return new Pair<>(eval, Math.max(1, configIoThreads));
});
private final BiFunction<Integer, Integer, Pair<Integer, Integer>> eval;
ChunkSystemAlgorithm(BiFunction<Integer, Integer, Pair<Integer, Integer>> eval) {
this.eval = eval;
}
private static int tryEvaluateExpression(String expression) {
return (int) Math.max(1,
new ExpressionBuilder(expression)
.variables("is_windows", "is_j9vm", "is_client", "cpus", "mem_gb")
.function(new Function("max", 2) {
@Override
public double apply(double... args) {
return Math.max(args[0], args[1]);
}
})
.function(new Function("min", 2) {
@Override
public double apply(double... args) {
return Math.min(args[0], args[1]);
}
})
.function(new Function("if", 3) {
@Override
public double apply(double... args) {
return args[0] != 0 ? args[1] : args[2];
}
})
.build()
.setVariable("is_windows", PlatformDependent.isWindows() ? 1 : 0)
.setVariable("is_j9vm", PlatformDependent.isJ9Jvm() ? 1 : 0)
.setVariable("is_client", 0)
.setVariable("cpus", Runtime.getRuntime().availableProcessors())
.setVariable("mem_gb", Runtime.getRuntime().maxMemory() / 1024.0 / 1024.0 / 1024.0)
.evaluate()
);
}
public int evalWorkers(final int configWorkerThreads, final int configIoThreads) {
return eval.apply(configWorkerThreads, configIoThreads).getA();
}
public int evalIO(final int configWorkerThreads, final int configIoThreads) {
return eval.apply(configWorkerThreads, configIoThreads).getB();
}
public @NotNull String asDebugString() {
return this + "(" + evalWorkers(-1, -1) + ")";
}
}

View File

@@ -7,6 +7,7 @@ import net.minecraft.world.entity.EntityType;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.bxteam.divinemc.chunk.ChunkSystemAlgorithm;
import org.bxteam.divinemc.config.annotations.Experimental;
import org.bxteam.divinemc.async.pathfinding.PathfindTaskRejectPolicy;
import org.bxteam.divinemc.region.EnumRegionFileExtension;
@@ -344,6 +345,7 @@ public class DivineConfig {
public static long chunkDataCacheLimit = 32678L;
public static int maxViewDistance = 32;
public static int playerNearChunkDetectionRange = 128;
public static ChunkSystemAlgorithm chunkWorkerAlgorithm = ChunkSystemAlgorithm.MOONRISE;
public static boolean useEuclideanDistanceSquared = true;
public static boolean endBiomeCacheEnabled = false;
public static int endBiomeCacheCapacity = 1024;
@@ -410,6 +412,13 @@ public class DivineConfig {
"This value is used in the calculation 'range/16' to get the distance in chunks any player must be to allow the check to pass.",
"By default, this range is computed to 8, meaning a player must be within an 8 chunk radius of a chunk position to pass.",
"Keep in mind the result is rounded to the nearest whole number.");
chunkWorkerAlgorithm = ChunkSystemAlgorithm.valueOf(getString(ConfigCategory.PERFORMANCE.key("chunks.chunk-worker-algorithm"), chunkWorkerAlgorithm.name(),
"Algorithm used to determine the number of worker threads for chunk loading and generation.",
"",
"Available algorithms:",
" - MOONRISE: Paper's default algorithm. Conservative approach, uses fewer threads (CPU cores / 2).",
" - C2ME: More aggressive thread allocation than MOONRISE. Considers both CPU cores and available memory. May use more threads on high-end systems.",
" - C2ME_NEW: Modern C2ME algorithm. Balanced approach between MOONRISE and C2ME. Optimized for current hardware, slightly less aggressive than old C2ME."));
useEuclideanDistanceSquared = getBoolean(ConfigCategory.PERFORMANCE.key("chunks.use-euclidean-distance-squared"), useEuclideanDistanceSquared,
"If enabled, euclidean distance squared for chunk task ordering will be used.");