From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Sun, 21 Mar 2021 11:22:10 -0700 Subject: [PATCH] Do not copy visible chunks For servers with a lot of chunk holders, copying for each tickDistanceManager call can take up quite a bit in the function. I saw approximately 1/3rd of the function on the copy. diff --git a/src/main/java/net/minecraft/server/ChunkSystem.java b/src/main/java/net/minecraft/server/ChunkSystem.java index 83dc09f6526206690c474b50a7a6e71cefc93ab4..7f76c304f5eb3c2f27b348918588ab67b795b1ba 100644 --- a/src/main/java/net/minecraft/server/ChunkSystem.java +++ b/src/main/java/net/minecraft/server/ChunkSystem.java @@ -202,19 +202,24 @@ public final class ChunkSystem { } public static List getVisibleChunkHolders(final ServerLevel level) { - return new ArrayList<>(level.chunkSource.chunkMap.visibleChunkMap.values()); + if (Bukkit.isPrimaryThread()) { + return level.chunkSource.chunkMap.updatingChunks.getVisibleValuesCopy(); + } + synchronized (level.chunkSource.chunkMap.updatingChunks) { + return level.chunkSource.chunkMap.updatingChunks.getVisibleValuesCopy(); + } } public static List getUpdatingChunkHolders(final ServerLevel level) { - return new ArrayList<>(level.chunkSource.chunkMap.updatingChunkMap.values()); + return level.chunkSource.chunkMap.updatingChunks.getUpdatingValuesCopy(); } public static int getVisibleChunkHolderCount(final ServerLevel level) { - return level.chunkSource.chunkMap.visibleChunkMap.size(); + return level.chunkSource.chunkMap.updatingChunks.getVisibleMap().size(); } public static int getUpdatingChunkHolderCount(final ServerLevel level) { - return level.chunkSource.chunkMap.updatingChunkMap.size(); + return level.chunkSource.chunkMap.updatingChunks.getUpdatingMap().size(); } public static boolean hasAnyChunkHolders(final ServerLevel level) { diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java index 2a9e5fb8164f79b0f9c1cb5497216e51f9df3454..ea27e6b1340a42c675bc68ed75f100569114be7a 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java @@ -121,9 +121,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider private static final int MIN_VIEW_DISTANCE = 3; public static final int MAX_VIEW_DISTANCE = 33; public static final int MAX_CHUNK_DISTANCE = 33 + ChunkStatus.maxDistance(); + // Paper start - Don't copy + public final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object updatingChunks = new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<>(); + // Paper end - Don't copy public static final int FORCED_TICKET_LEVEL = 31; - public final Long2ObjectLinkedOpenHashMap updatingChunkMap = new Long2ObjectLinkedOpenHashMap(); - public volatile Long2ObjectLinkedOpenHashMap visibleChunkMap; + // Paper - Don't copy private final Long2ObjectLinkedOpenHashMap pendingUnloads; public final LongSet entitiesInLevel; public final ServerLevel level; @@ -224,7 +226,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider public ChunkMap(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureTemplateManager structureTemplateManager, Executor executor, BlockableEventLoop mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier persistentStateManagerFactory, int viewDistance, boolean dsync) { super(session.getDimensionPath(world.dimension()).resolve("region"), dataFixer, dsync); - this.visibleChunkMap = this.updatingChunkMap.clone(); + // Paper - don't copy this.pendingUnloads = new Long2ObjectLinkedOpenHashMap(); this.entitiesInLevel = new LongOpenHashSet(); this.toDrop = new LongOpenHashSet(); @@ -327,12 +329,17 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @Nullable public ChunkHolder getUpdatingChunkIfPresent(long pos) { - return (ChunkHolder) this.updatingChunkMap.get(pos); + return this.updatingChunks.getUpdating(pos); // Paper - Don't copy } @Nullable public ChunkHolder getVisibleChunkIfPresent(long pos) { - return (ChunkHolder) this.visibleChunkMap.get(pos); + // Paper start - Don't copy + if (Thread.currentThread() == this.level.thread) { + return this.updatingChunks.getVisible(pos); + } + return this.updatingChunks.getVisibleAsync(pos); + // Paper end - Don't copy } protected IntSupplier getChunkQueueLevel(long pos) { @@ -515,7 +522,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider // Paper start holder.onChunkAdd(); // Paper end - this.updatingChunkMap.put(pos, holder); + this.updatingChunks.queueUpdate(pos, holder); // Paper - Don't copy this.modified = true; } @@ -592,7 +599,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider for (int i = 0; longiterator.hasNext() && (shouldKeepTicking.getAsBoolean() || i < 200 || this.toDrop.size() > 2000); longiterator.remove()) { long j = longiterator.nextLong(); - ChunkHolder playerchunk = (ChunkHolder) this.updatingChunkMap.remove(j); + ChunkHolder playerchunk = this.updatingChunks.queueRemove(j); // Paper - Don't copy if (playerchunk != null) { playerchunk.onChunkRemove(); // Paper @@ -672,7 +679,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider if (!this.modified) { return false; } else { - this.visibleChunkMap = this.updatingChunkMap.clone(); + // Paper start - Don't copy + synchronized (this.updatingChunks) { + this.updatingChunks.performUpdates(); + } + // Paper end - Don't copy + this.modified = false; return true; }