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:
@@ -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")
|
||||
|
||||
@@ -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.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.");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user