mirror of
https://github.com/BX-Team/DivineMC.git
synced 2025-12-20 15:29:15 +00:00
add back chunk system algorithms
This commit is contained in:
@@ -72,7 +72,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
val log4jPlugins = sourceSets.create("log4jPlugins") {
|
val log4jPlugins = sourceSets.create("log4jPlugins") {
|
||||||
@@ -154,10 +_,22 @@
|
@@ -154,10 +_,23 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@@ -88,6 +88,7 @@
|
|||||||
+ implementation("org.lz4:lz4-java:1.8.0")
|
+ implementation("org.lz4:lz4-java:1.8.0")
|
||||||
+ implementation("net.openhft:zero-allocation-hashing:0.16")
|
+ implementation("net.openhft:zero-allocation-hashing:0.16")
|
||||||
+ implementation("org.agrona:agrona:2.2.4")
|
+ implementation("org.agrona:agrona:2.2.4")
|
||||||
|
+ implementation("net.objecthunter:exp4j:0.4.8")
|
||||||
+ // DivineMC end - Dependencies
|
+ // DivineMC end - Dependencies
|
||||||
+
|
+
|
||||||
implementation("ca.spottedleaf:concurrentutil:0.0.5")
|
implementation("ca.spottedleaf:concurrentutil:0.0.5")
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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) + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ import net.minecraft.world.entity.EntityType;
|
|||||||
import org.apache.logging.log4j.Level;
|
import org.apache.logging.log4j.Level;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.bxteam.divinemc.chunk.ChunkSystemAlgorithm;
|
||||||
import org.bxteam.divinemc.config.annotations.Experimental;
|
import org.bxteam.divinemc.config.annotations.Experimental;
|
||||||
import org.bxteam.divinemc.async.pathfinding.PathfindTaskRejectPolicy;
|
import org.bxteam.divinemc.async.pathfinding.PathfindTaskRejectPolicy;
|
||||||
import org.bxteam.divinemc.region.EnumRegionFileExtension;
|
import org.bxteam.divinemc.region.EnumRegionFileExtension;
|
||||||
@@ -344,6 +345,7 @@ public class DivineConfig {
|
|||||||
public static long chunkDataCacheLimit = 32678L;
|
public static long chunkDataCacheLimit = 32678L;
|
||||||
public static int maxViewDistance = 32;
|
public static int maxViewDistance = 32;
|
||||||
public static int playerNearChunkDetectionRange = 128;
|
public static int playerNearChunkDetectionRange = 128;
|
||||||
|
public static ChunkSystemAlgorithm chunkWorkerAlgorithm = ChunkSystemAlgorithm.MOONRISE;
|
||||||
public static boolean useEuclideanDistanceSquared = true;
|
public static boolean useEuclideanDistanceSquared = true;
|
||||||
public static boolean endBiomeCacheEnabled = false;
|
public static boolean endBiomeCacheEnabled = false;
|
||||||
public static int endBiomeCacheCapacity = 1024;
|
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.",
|
"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.",
|
"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.");
|
"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,
|
useEuclideanDistanceSquared = getBoolean(ConfigCategory.PERFORMANCE.key("chunks.use-euclidean-distance-squared"), useEuclideanDistanceSquared,
|
||||||
"If enabled, euclidean distance squared for chunk task ordering will be used.");
|
"If enabled, euclidean distance squared for chunk task ordering will be used.");
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user