mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-29 07:48:53 +01:00
Add config options to paper.yml for Async Chunks and Shared Host Overrides
Shared Hosts have been concerned over the increased CPU usage that Async Chunks has introduced. We understand that shared hosts can't allow 1 client to abuse the systme resources depriving other servers of cpu time, so we've added some configs to allow hosts to force some settings. Hosts, you may set the following SYSTEM ENVIRONMENT VARIABLES (NOT JVM FLAGS) to change some behavior: PAPER_ASYNC_CHUNKS_SHARED_HOST_GEN=1 - Enable Single Threaded World Generation (capping CPU Usage PAPER_ASYNC_CHUNKS_SHARED_HOST_GEN=2 - Disable Async Chunk Generation - Please do not do this!!! - Minecraft is moving towards asynchronousm per-world chunk generation itself. You need to prepare - for this, so please do not disable async chunk generation. PAPER_ASYNC_CHUNKS_SHARED_HOST_LOAD=# - Where # is Maximum number of threads to use on Chunk Loading - This is a max, so your end user can reduce it more too. I suggest no lower than 2. Minimum is 1. - These are usually much faster request, so outside of loading entire worlds, They usually do not - get as much load. Paperby default uses CPU Core count * 1.5, so this may default to a higher value - on shared host and you should override it with this value to say 2-4. These settings will override your clients paper.yml options. Set as a system wide environment variable to ensure all Paper clients respect your resource usage desires. Resolves #1520
This commit is contained in:
parent
10209bfbd8
commit
a64b0952cb
2 changed files with 82 additions and 37 deletions
|
@ -1,4 +1,4 @@
|
|||
From 800d7c783d6ed1be96b675b15a31a04c0cf3bb6e Mon Sep 17 00:00:00 2001
|
||||
From a8159e0501c03d8ee285f2bd6d19bdf3e52d5cf8 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach.brown@destroystokyo.com>
|
||||
Date: Mon, 29 Feb 2016 21:02:09 -0600
|
||||
Subject: [PATCH] Paper config files
|
||||
|
@ -6,7 +6,7 @@ Subject: [PATCH] Paper config files
|
|||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java
|
||||
new file mode 100644
|
||||
index 000000000..961966e16
|
||||
index 0000000000..961966e169
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java
|
||||
@@ -0,0 +1,237 @@
|
||||
|
@ -249,7 +249,7 @@ index 000000000..961966e16
|
|||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
new file mode 100644
|
||||
index 000000000..104abab84
|
||||
index 0000000000..92e44befe0
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
@@ -0,0 +1,177 @@
|
||||
|
@ -313,7 +313,7 @@ index 000000000..104abab84
|
|||
+ commands.put("paper", new PaperCommand("paper"));
|
||||
+
|
||||
+ version = getInt("config-version", 14);
|
||||
+ set("config-version", 14);
|
||||
+ set("config-version", 15);
|
||||
+ readConfig(PaperConfig.class, null);
|
||||
+ }
|
||||
+
|
||||
|
@ -432,7 +432,7 @@ index 000000000..104abab84
|
|||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
new file mode 100644
|
||||
index 000000000..a73865739
|
||||
index 0000000000..a738657394
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
@@ -0,0 +1,67 @@
|
||||
|
@ -504,7 +504,7 @@ index 000000000..a73865739
|
|||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/server/DedicatedServer.java b/src/main/java/net/minecraft/server/DedicatedServer.java
|
||||
index 8b3988fc0..d8535fdd9 100644
|
||||
index 8b3988fc0a..d8535fdd9e 100644
|
||||
--- a/src/main/java/net/minecraft/server/DedicatedServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/DedicatedServer.java
|
||||
@@ -192,6 +192,10 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer
|
||||
|
@ -519,7 +519,7 @@ index 8b3988fc0..d8535fdd9 100644
|
|||
DedicatedServer.LOGGER.info("Generating keypair");
|
||||
this.a(MinecraftEncryption.b());
|
||||
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
|
||||
index 709b28d78..4ba748ae2 100644
|
||||
index 3c7537d013..ffaa425ec8 100644
|
||||
--- a/src/main/java/net/minecraft/server/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/server/Entity.java
|
||||
@@ -135,9 +135,9 @@ public abstract class Entity implements INamableTileEntity, ICommandListener {
|
||||
|
@ -536,7 +536,7 @@ index 709b28d78..4ba748ae2 100644
|
|||
public boolean impulse;
|
||||
public int portalCooldown;
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityTypes.java b/src/main/java/net/minecraft/server/EntityTypes.java
|
||||
index c6434ec37..17bfa356f 100644
|
||||
index c6434ec371..17bfa356f1 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityTypes.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityTypes.java
|
||||
@@ -2,6 +2,8 @@ package net.minecraft.server;
|
||||
|
@ -560,7 +560,7 @@ index c6434ec37..17bfa356f 100644
|
|||
+ // Paper end
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
|
||||
index ed77641e4..f381e23be 100644
|
||||
index ed77641e46..f381e23beb 100644
|
||||
--- a/src/main/java/net/minecraft/server/World.java
|
||||
+++ b/src/main/java/net/minecraft/server/World.java
|
||||
@@ -134,6 +134,8 @@ public abstract class World implements IEntityAccess, GeneratorAccess, IIBlockAc
|
||||
|
@ -581,7 +581,7 @@ index ed77641e4..f381e23be 100644
|
|||
this.world = new CraftWorld((WorldServer) this, gen, env);
|
||||
this.ticksPerAnimalSpawns = this.getServer().getTicksPerAnimalSpawns(); // CraftBukkit
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index e28ce05fb..e659f3f33 100644
|
||||
index e28ce05fb9..e659f3f339 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -750,6 +750,7 @@ public final class CraftServer implements Server {
|
||||
|
@ -636,7 +636,7 @@ index e28ce05fb..e659f3f33 100644
|
|||
+ // Paper end
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||
index 4a998593b..e354245f7 100644
|
||||
index 4a998593bd..e354245f73 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||
@@ -128,6 +128,14 @@ public class Main {
|
||||
|
@ -655,7 +655,7 @@ index 4a998593b..e354245f7 100644
|
|||
};
|
||||
|
||||
diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java
|
||||
index 95f7a9587..87bc8e2d9 100644
|
||||
index 95f7a9587a..87bc8e2d9c 100644
|
||||
--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java
|
||||
+++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java
|
||||
@@ -39,31 +39,31 @@ public class SpigotWorldConfig
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
From 523a76f0b9a204e83620100df735b2228c22306e Mon Sep 17 00:00:00 2001
|
||||
From 5b1ddb18ea0397774eed24f27ab4d3fe2449141c Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 21 Jul 2018 16:55:04 -0400
|
||||
Subject: [PATCH] Async Chunk Loading and Generation
|
||||
|
@ -43,22 +43,64 @@ reading or writing to the chunk will be safe, so plugins still
|
|||
should not be touching chunks asynchronously!
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
index da710cc6fe..6b65364e22 100644
|
||||
index 912c990404..2f6d7f2976 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
@@ -372,4 +372,15 @@ public class PaperConfig {
|
||||
@@ -372,4 +372,57 @@ public class PaperConfig {
|
||||
}
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // Temporary opt out, will be removed later
|
||||
+ public static boolean asyncChunks = false;
|
||||
+ private static void disableAsyncChunks() {
|
||||
+ asyncChunks = config.getBoolean("settings.async-chunks", true);
|
||||
+ public static boolean asyncChunkGeneration = true;
|
||||
+ public static boolean asyncChunkGenThreadPerWorld = true;
|
||||
+ public static int asyncChunkLoadThreads = -1;
|
||||
+ private static void asyncChunks() {
|
||||
+ if (version < 15) {
|
||||
+ boolean enabled = config.getBoolean("settings.async-chunks", true);
|
||||
+ ConfigurationSection section = config.createSection("settings.async-chunks");
|
||||
+ section.set("enable", enabled);
|
||||
+ section.set("load-threads", -1);
|
||||
+ section.set("generation", true);
|
||||
+ section.set("thread-per-world-generation", true);
|
||||
+ }
|
||||
+
|
||||
+ asyncChunks = getBoolean("settings.async-chunks.enable", true);
|
||||
+ asyncChunkGeneration = getBoolean("settings.async-chunks.generation", true);
|
||||
+ asyncChunkGenThreadPerWorld = getBoolean("settings.async-chunks.thread-per-world-generation", true);
|
||||
+ asyncChunkLoadThreads = getInt("settings.async-chunks.load-threads", -1);
|
||||
+ if (asyncChunkLoadThreads <= 0) {
|
||||
+ asyncChunkLoadThreads = (int) Math.min(Integer.getInteger("paper.maxchunkthreads", 8), Runtime.getRuntime().availableProcessors() * 1.5);
|
||||
+ }
|
||||
+
|
||||
+ // Let Shared Host set some limits
|
||||
+ String sharedHostEnvGen = System.getenv("PAPER_ASYNC_CHUNKS_SHARED_HOST_GEN");
|
||||
+ String sharedHostEnvLoad = System.getenv("PAPER_ASYNC_CHUNKS_SHARED_HOST_LOAD");
|
||||
+ if ("1".equals(sharedHostEnvGen)) {
|
||||
+ log("Async Chunks - Generation: Your host has requested to use a single thread world generation");
|
||||
+ asyncChunkGenThreadPerWorld = false;
|
||||
+ } else if ("2".equals(sharedHostEnvGen)) {
|
||||
+ log("Async Chunks - Generation: Your host has disabled async world generation - You will experience lag from world generation");
|
||||
+ asyncChunkGeneration = false;
|
||||
+ }
|
||||
+
|
||||
+ if (sharedHostEnvLoad != null) {
|
||||
+ try {
|
||||
+ asyncChunkLoadThreads = Math.max(1, Math.min(asyncChunkLoadThreads, Integer.parseInt(sharedHostEnvLoad)));
|
||||
+ } catch (NumberFormatException ignored) {}
|
||||
+ }
|
||||
+
|
||||
+ if (!asyncChunks) {
|
||||
+ log("Async Chunks: Disabled - Chunks will be managed synchronosuly, and will cause tremendous lag.");
|
||||
+ } else {
|
||||
+ log("Async Chunks: Enabled - Chunks will be loaded and generated much faster, without lag.");
|
||||
+ log("Async Chunks: Enabled - Chunks will be loaded much faster, without lag.");
|
||||
+ if (!asyncChunkGeneration) {
|
||||
+ log("Async Chunks - Generation: Disabled - Chunks will be generated synchronosuly, and will cause tremendous lag.");
|
||||
+ } else if (asyncChunkGenThreadPerWorld) {
|
||||
+ log("Async Chunks - Generation: Enabled - Chunks will be generated much faster, without lag.");
|
||||
+ } else {
|
||||
+ log("Async Chunks - Generation: Enabled (Single Thread) - Chunks will be generated much faster, without lag.");
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
@ -794,10 +836,10 @@ index 98d182fdb8..487d98eb1b 100644
|
|||
|
||||
diff --git a/src/main/java/net/minecraft/server/PaperAsyncChunkProvider.java b/src/main/java/net/minecraft/server/PaperAsyncChunkProvider.java
|
||||
new file mode 100644
|
||||
index 0000000000..a3fc989832
|
||||
index 0000000000..1c592c7956
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/net/minecraft/server/PaperAsyncChunkProvider.java
|
||||
@@ -0,0 +1,478 @@
|
||||
@@ -0,0 +1,477 @@
|
||||
+/*
|
||||
+ * This file is licensed under the MIT License (MIT).
|
||||
+ *
|
||||
|
@ -846,8 +888,8 @@ index 0000000000..a3fc989832
|
|||
+public class PaperAsyncChunkProvider extends ChunkProviderServer {
|
||||
+
|
||||
+ private static final PriorityQueuedExecutor.RejectionHandler IGNORE_HANDLER = (run, executor) -> {};
|
||||
+ private static final int CHUNK_THREADS = (int) Math.min(Integer.getInteger("paper.maxchunkthreads", 8), Runtime.getRuntime().availableProcessors() * 1.5);
|
||||
+ private static final PriorityQueuedExecutor EXECUTOR = new PriorityQueuedExecutor("PaperChunkLoader", PaperConfig.asyncChunks ? CHUNK_THREADS : 0, IGNORE_HANDLER);
|
||||
+ private static final PriorityQueuedExecutor EXECUTOR = new PriorityQueuedExecutor("PaperChunkLoader", PaperConfig.asyncChunks ? PaperConfig.asyncChunkLoadThreads : 0, IGNORE_HANDLER);
|
||||
+ private static final PriorityQueuedExecutor SINGLE_GEN_EXECUTOR = new PriorityQueuedExecutor("PaperChunkGenerator", PaperConfig.asyncChunks && PaperConfig.asyncChunkGeneration && !PaperConfig.asyncChunkGenThreadPerWorld ? 1 : 0, IGNORE_HANDLER);
|
||||
+
|
||||
+ private final PriorityQueuedExecutor generationExecutor;
|
||||
+ //private static final PriorityQueuedExecutor generationExecutor = new PriorityQueuedExecutor("PaperChunkGen", 1);
|
||||
|
@ -868,8 +910,8 @@ index 0000000000..a3fc989832
|
|||
+ this.asyncHandler = server;
|
||||
+ this.chunkLoader = chunkLoader;
|
||||
+ String worldName = this.world.getWorld().getName();
|
||||
+ this.shouldGenSync = generator instanceof CustomChunkGenerator && !(((CustomChunkGenerator) generator).asyncSupported);
|
||||
+ this.generationExecutor = new PriorityQueuedExecutor("PaperChunkGen-" + worldName, shouldGenSync ? 0 : 1, IGNORE_HANDLER);
|
||||
+ this.shouldGenSync = generator instanceof CustomChunkGenerator && !(((CustomChunkGenerator) generator).asyncSupported) || !PaperConfig.asyncChunkGeneration;
|
||||
+ this.generationExecutor = PaperConfig.asyncChunkGenThreadPerWorld ? new PriorityQueuedExecutor("PaperChunkGen-" + worldName, shouldGenSync ? 0 : 1, IGNORE_HANDLER) : SINGLE_GEN_EXECUTOR;
|
||||
+ }
|
||||
+
|
||||
+ static void processChunkLoads(MinecraftServer server) {
|
||||
|
@ -1176,13 +1218,12 @@ index 0000000000..a3fc989832
|
|||
+ this.chunk = chunk;
|
||||
+ this.hasFinished = true;
|
||||
+ }
|
||||
+ if (Bukkit.isPrimaryThread()) {
|
||||
+ postChunk();
|
||||
+ } else {
|
||||
+ synchronized (mainThreadQueue) {
|
||||
+ mainThreadQueue.add(this::postChunk);
|
||||
+ mainThreadQueue.notify();
|
||||
+ }
|
||||
+
|
||||
+ // Don't post here, even if on main, it must enter the queue so we can exit any open batch
|
||||
+ // schedulers, as post stage may trigger a new generation and cause errors
|
||||
+ synchronized (mainThreadQueue) {
|
||||
+ mainThreadQueue.add(this::postChunk);
|
||||
+ mainThreadQueue.notify();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
|
@ -1410,7 +1451,7 @@ index 3c35c0f481..187ca2813a 100644
|
|||
this.m = world.getChunkProvider().getChunkGenerator().getSettings();
|
||||
this.i = world.getSeaLevel();
|
||||
diff --git a/src/main/java/net/minecraft/server/SchedulerBatch.java b/src/main/java/net/minecraft/server/SchedulerBatch.java
|
||||
index d868149d1a..0d94b262ac 100644
|
||||
index d868149d1a..0d45d933ee 100644
|
||||
--- a/src/main/java/net/minecraft/server/SchedulerBatch.java
|
||||
+++ b/src/main/java/net/minecraft/server/SchedulerBatch.java
|
||||
@@ -9,6 +9,7 @@ public class SchedulerBatch<K, T extends SchedulerTask<K, T>, R> {
|
||||
|
@ -1421,16 +1462,18 @@ index d868149d1a..0d94b262ac 100644
|
|||
|
||||
public SchedulerBatch(Scheduler<K, T, R> scheduler) {
|
||||
this.b = scheduler;
|
||||
@@ -18,7 +19,9 @@ public class SchedulerBatch<K, T extends SchedulerTask<K, T>, R> {
|
||||
@@ -18,8 +19,10 @@ public class SchedulerBatch<K, T extends SchedulerTask<K, T>, R> {
|
||||
this.b.b();
|
||||
}
|
||||
|
||||
+ public void startBatch() { b(); } // Paper - OBFHELPER
|
||||
public void b() {
|
||||
- if (this.c) {
|
||||
+ lock.lock(); // Paper
|
||||
if (this.c) {
|
||||
+ if (false && this.c) { // Paper
|
||||
throw new RuntimeException("Batch already started.");
|
||||
} else {
|
||||
this.d = 1000;
|
||||
@@ -27,6 +30,7 @@ public class SchedulerBatch<K, T extends SchedulerTask<K, T>, R> {
|
||||
}
|
||||
}
|
||||
|
@ -1439,20 +1482,22 @@ index d868149d1a..0d94b262ac 100644
|
|||
public CompletableFuture<R> a(K object) {
|
||||
if (!this.c) {
|
||||
throw new RuntimeException("Batch not properly started. Please use startBatch to create a new batch.");
|
||||
@@ -42,7 +46,13 @@ public class SchedulerBatch<K, T extends SchedulerTask<K, T>, R> {
|
||||
@@ -42,8 +46,14 @@ public class SchedulerBatch<K, T extends SchedulerTask<K, T>, R> {
|
||||
}
|
||||
}
|
||||
|
||||
+ public CompletableFuture<R> executeBatch() { return c(); } // Paper - OBFHELPER
|
||||
public CompletableFuture<R> c() {
|
||||
- if (!this.c) {
|
||||
+ // Paper start
|
||||
+ if (!lock.isHeldByCurrentThread()) {
|
||||
+ throw new IllegalStateException("Current thread does not hold the write lock");
|
||||
+ }
|
||||
+ try {// Paper end
|
||||
if (!this.c) {
|
||||
+ if (false && !this.c) { // Paper
|
||||
throw new RuntimeException("Batch not properly started. Please use startBatch to create a new batch.");
|
||||
} else {
|
||||
if (this.d != 1000) {
|
||||
@@ -53,5 +63,6 @@ public class SchedulerBatch<K, T extends SchedulerTask<K, T>, R> {
|
||||
this.c = false;
|
||||
return this.b.c();
|
||||
|
|
Loading…
Reference in a new issue