aboutsummaryrefslogtreecommitdiffhomepage
path: root/Spigot-Server-Patches/0528-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch
diff options
context:
space:
mode:
Diffstat (limited to 'Spigot-Server-Patches/0528-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch')
-rw-r--r--Spigot-Server-Patches/0528-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch72
1 files changed, 72 insertions, 0 deletions
diff --git a/Spigot-Server-Patches/0528-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch b/Spigot-Server-Patches/0528-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch
new file mode 100644
index 0000000000..29b5e63ec6
--- /dev/null
+++ b/Spigot-Server-Patches/0528-Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch
@@ -0,0 +1,72 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Aikar <[email protected]>
+Date: Sat, 23 May 2020 01:31:06 -0400
+Subject: [PATCH] Fix Non Full Status Chunk NBT Memory Leak
+
+Any full status chunk that was requested for any status less than full
+would hold onto their entire nbt tree and every variable in that function.
+
+This was due to use of a lambda that persists on the Chunk object
+until that chunk reaches FULL status.
+
+With introduction of no tick, we greatly increased the number of non
+full chunks so this was really starting to hurt.
+
+We further improve it by making a copy of the nbt tag with only the memory
+it needs, so that we dont have to hold a copy to the entire compound.
+
+diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
+index d752e793f13a9caf5d255293f7ce9d562fd50064..1685237dfd7d6f352c5bab5f65817462de5e6d12 100644
+--- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java
++++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
+@@ -157,9 +157,9 @@ public class ChunkRegionLoader {
+ object2 = protochunkticklist1;
+ }
+
+- object = new Chunk(worldserver.getMinecraftWorld(), chunkcoordintpair, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, j, achunksection, (chunk) -> {
+- loadEntities(nbttagcompound1, chunk);
+- });
++ object = new Chunk(worldserver.getMinecraftWorld(), chunkcoordintpair, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, j, achunksection, // Paper start - fix massive nbt memory leak due to lambda. move lambda into a container method to not leak scope. Only clone needed NBT keys.
++ createLoadEntitiesConsumer(new SafeNBTCopy(nbttagcompound1, "TileEntities", "Entities"))
++ );// Paper end
+ } else {
+ ProtoChunk protochunk = new ProtoChunk(chunkcoordintpair, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, worldserver); // Paper - Anti-Xray - Add parameter
+
+@@ -265,6 +265,37 @@ public class ChunkRegionLoader {
+ return new InProgressChunkHolder(protochunk1, tasksToExecuteOnMain); // Paper - Async chunk loading
+ }
+ }
++ // Paper start
++
++ /**
++ * This wrapper will error out if any key is accessed that wasn't copied so we can catch it easy on an update
++ */
++ private static class SafeNBTCopy extends NBTTagCompound {
++ private final java.util.Set<String> keys = new java.util.HashSet<String>();
++ public SafeNBTCopy(NBTTagCompound base, String... keys) {
++ for (String key : keys) {
++ this.keys.add(key);
++ this.set(key, base.get(key));
++ }
++ }
++
++ @Override
++ public boolean hasKey(String s) {
++ if (this.keys.contains(s)) {
++ return true;
++ }
++ throw new IllegalStateException("Missing Key " + s + " in SafeNBTCopy");
++ }
++
++ @Override
++ public boolean hasKeyOfType(String s, int i) {
++ return hasKey(s) && super.hasKeyOfType(s, i);
++ }
++ }
++ private static java.util.function.Consumer<Chunk> createLoadEntitiesConsumer(NBTTagCompound nbt) {
++ return (chunk) -> loadEntities(nbt, chunk);
++ }
++ // Paper end
+
+ // Paper start - async chunk save for unload
+ public static final class AsyncSaveData {