Add per player chunk loading limits

Configurable under "settings.chunk-loading.player-max-chunk-load-rate",
defaults to -1. This commit also changes the chunk loading to be
distributed equally for all players, rather than distance based. This is
to ensure players flying around do not take priority over everyone else.
The exception to this new rule is the min-load-radius, which still has
priority over everything else.
This commit is contained in:
Spottedleaf
2022-03-31 06:04:23 -07:00
parent 5c7b445c76
commit a096540d94
6 changed files with 124 additions and 19 deletions

View File

@@ -102,6 +102,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ public static double globalMaxChunkLoadRate;
+ public static double playerMaxConcurrentChunkLoads;
+ public static double globalMaxConcurrentChunkLoads;
+ public static double playerMaxChunkLoadRate;
+
+ private static void newPlayerChunkManagement() {
+ playerMinChunkLoadRadius = getInt("settings.chunk-loading.min-load-radius", 2);
@@ -119,6 +120,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ set("settings.chunk-loading.player-max-concurrent-loads", playerMaxConcurrentChunkLoads = 20.0);
+ }
+ globalMaxConcurrentChunkLoads = getDouble("settings.chunk-loading.global-max-concurrent-loads", 500.0);
+ playerMaxChunkLoadRate = getDouble("settings.chunk-loading.player-max-chunk-load-rate", -1.0);
+ }
}
diff --git a/src/main/java/io/papermc/paper/chunk/PlayerChunkLoader.java b/src/main/java/io/papermc/paper/chunk/PlayerChunkLoader.java
@@ -218,10 +220,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+
+ final int priorityCompare = Double.compare(holder1 == null ? Double.MAX_VALUE : holder1.priority, holder2 == null ? Double.MAX_VALUE : holder2.priority);
+
+ if (priorityCompare != 0) {
+ final int lastLoadTimeCompare = Long.compare(p1.lastChunkLoad, p2.lastChunkLoad);
+
+ if ((holder1 == null || holder2 == null || lastLoadTimeCompare == 0 || holder1.priority < 0.0 || holder2.priority < 0.0) && priorityCompare != 0) {
+ return priorityCompare;
+ }
+
+ if (lastLoadTimeCompare != 0) {
+ return lastLoadTimeCompare;
+ }
+
+ final int idCompare = Integer.compare(p1.player.getId(), p2.player.getId());
+
+ if (idCompare != 0) {
@@ -744,6 +752,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ for (;;) {
+ final PlayerLoaderData data = this.chunkLoadQueue.pollFirst();
+
+ data.lastChunkLoad = time;
+
+ final ChunkPriorityHolder queuedLoad = data.loadQueue.peekFirst();
+ if (queuedLoad == null) {
+ if (this.chunkLoadQueue.isEmpty()) {
@@ -756,6 +766,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ updatedCounters = true;
+ TICKET_ADDITION_COUNTER_SHORT.updateCurrentTime(time);
+ TICKET_ADDITION_COUNTER_LONG.updateCurrentTime(time);
+ data.ticketAdditionCounterShort.updateCurrentTime(time);
+ data.ticketAdditionCounterLong.updateCurrentTime(time);
+ }
+
+ if (this.isChunkPlayerLoaded(queuedLoad.chunkX, queuedLoad.chunkZ)) {
@@ -791,7 +803,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // priority >= 0.0 implies rate limited chunks
+
+ final int currentChunkLoads = this.concurrentChunkLoads;
+ if (currentChunkLoads >= maxLoads || (PaperConfig.globalMaxChunkLoadRate > 0 && (TICKET_ADDITION_COUNTER_SHORT.getRate() >= PaperConfig.globalMaxChunkLoadRate || TICKET_ADDITION_COUNTER_LONG.getRate() >= PaperConfig.globalMaxChunkLoadRate))) {
+ if (currentChunkLoads >= maxLoads || (PaperConfig.globalMaxChunkLoadRate > 0 && (TICKET_ADDITION_COUNTER_SHORT.getRate() >= PaperConfig.globalMaxChunkLoadRate || TICKET_ADDITION_COUNTER_LONG.getRate() >= PaperConfig.globalMaxChunkLoadRate))
+ || (PaperConfig.playerMaxChunkLoadRate > 0.0 && (data.ticketAdditionCounterShort.getRate() >= PaperConfig.playerMaxChunkLoadRate || data.ticketAdditionCounterLong.getRate() >= PaperConfig.playerMaxChunkLoadRate))) {
+ // don't poll, we didn't load it
+ this.chunkLoadQueue.add(data);
+ break;
@@ -821,6 +834,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ ++this.concurrentChunkLoads;
+ TICKET_ADDITION_COUNTER_SHORT.addTime(time);
+ TICKET_ADDITION_COUNTER_LONG.addTime(time);
+ data.ticketAdditionCounterShort.addTime(time);
+ data.ticketAdditionCounterLong.addTime(time);
+ }
+ }
+ }
@@ -926,6 +941,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+
+ protected long nextChunkSendTarget;
+
+ // this interval prevents bursting a lot of chunk loads
+ protected final IntervalledCounter ticketAdditionCounterShort = new IntervalledCounter((long)(1.0e6 * 50.0)); // 50ms
+ // this ensures the rate is kept between ticks correctly
+ protected final IntervalledCounter ticketAdditionCounterLong = new IntervalledCounter((long)(1.0e6 * 1000.0)); // 1000ms
+
+ public long lastChunkLoad;
+
+ public PlayerLoaderData(final ServerPlayer player, final PlayerChunkLoader loader) {
+ this.player = player;
+ this.loader = loader;