diff options
Diffstat (limited to 'patches/removed/1.18/No longer needed/0463-Optimize-NibbleArray-to-use-pooled-buffers.patch')
-rw-r--r-- | patches/removed/1.18/No longer needed/0463-Optimize-NibbleArray-to-use-pooled-buffers.patch | 378 |
1 files changed, 0 insertions, 378 deletions
diff --git a/patches/removed/1.18/No longer needed/0463-Optimize-NibbleArray-to-use-pooled-buffers.patch b/patches/removed/1.18/No longer needed/0463-Optimize-NibbleArray-to-use-pooled-buffers.patch deleted file mode 100644 index bff1c4bc34..0000000000 --- a/patches/removed/1.18/No longer needed/0463-Optimize-NibbleArray-to-use-pooled-buffers.patch +++ /dev/null @@ -1,378 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar <[email protected]> -Date: Wed, 6 May 2020 23:30:30 -0400 -Subject: [PATCH] Optimize NibbleArray to use pooled buffers - -Massively reduces memory allocation of 2048 byte buffers by using -an object pool for these. - -Uses lots of advanced new capabilities of the Paper codebase :) - -diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket.java -index 7825d6f0fdcfda6212cff8033ec55fb7db236154..2218ddb8d075d042bb7c41886aa9dd2082a5a40f 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket.java -@@ -2,8 +2,11 @@ package net.minecraft.network.protocol.game; - - import java.util.BitSet; - import javax.annotation.Nullable; -+ -+import io.netty.channel.ChannelFuture; - import net.minecraft.network.FriendlyByteBuf; - import net.minecraft.network.protocol.Packet; -+import net.minecraft.server.level.ServerPlayer; - import net.minecraft.world.level.ChunkPos; - import net.minecraft.world.level.chunk.LevelChunk; - import net.minecraft.world.level.lighting.LevelLightEngine; -@@ -14,6 +17,23 @@ public class ClientboundLevelChunkWithLightPacket implements Packet<ClientGamePa - private final ClientboundLevelChunkPacketData chunkData; - private final ClientboundLightUpdatePacketData lightData; - -+ // Paper start -+ @Override -+ public void onPacketDispatch(ServerPlayer player) { -+ lightData.onPacketDispatch(player); -+ } -+ -+ @Override -+ public void onPacketDispatchFinish(ServerPlayer player, ChannelFuture future) { -+ lightData.onPacketDispatchFinish(player, future); -+ } -+ -+ @Override -+ public boolean hasFinishListener() { -+ return true; -+ } -+ // Paper end -+ - public ClientboundLevelChunkWithLightPacket(LevelChunk chunk, LevelLightEngine lightProvider, @Nullable BitSet skyBits, @Nullable BitSet blockBits, boolean nonEdge) { - ChunkPos chunkPos = chunk.getPos(); - this.x = chunkPos.x; -diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLightUpdatePacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLightUpdatePacket.java -index 15350c301ba670cd86c83c7051c3571ff2759d8f..da46695e4d45f701a216767a048b21e289f056f6 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLightUpdatePacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLightUpdatePacket.java -@@ -2,8 +2,11 @@ package net.minecraft.network.protocol.game; - - import java.util.BitSet; - import javax.annotation.Nullable; -+ -+import io.netty.channel.ChannelFuture; - import net.minecraft.network.FriendlyByteBuf; - import net.minecraft.network.protocol.Packet; -+import net.minecraft.server.level.ServerPlayer; - import net.minecraft.world.level.ChunkPos; - import net.minecraft.world.level.lighting.LevelLightEngine; - -@@ -12,6 +15,23 @@ public class ClientboundLightUpdatePacket implements Packet<ClientGamePacketList - private final int z; - private final ClientboundLightUpdatePacketData lightData; - -+ // Paper start -+ @Override -+ public void onPacketDispatch(ServerPlayer player) { -+ lightData.onPacketDispatch(player); -+ } -+ -+ @Override -+ public void onPacketDispatchFinish(ServerPlayer player, ChannelFuture future) { -+ lightData.onPacketDispatchFinish(player, future); -+ } -+ -+ @Override -+ public boolean hasFinishListener() { -+ return true; -+ } -+ // Paper end -+ - public ClientboundLightUpdatePacket(ChunkPos chunkPos, LevelLightEngine lightProvider, @Nullable BitSet skyBits, @Nullable BitSet blockBits, boolean nonEdge) { - this.x = chunkPos.x; - this.z = chunkPos.z; -diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLightUpdatePacketData.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLightUpdatePacketData.java -index fe9cfb2c6e3ecbe8966bc33a16785f03f870e7cf..e887317e8fcf71740ec96d85b7ea5b819a39d468 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLightUpdatePacketData.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLightUpdatePacketData.java -@@ -19,6 +19,27 @@ public class ClientboundLightUpdatePacketData { - private final List<byte[]> skyUpdates; - private final List<byte[]> blockUpdates; - private final boolean trustEdges; -+ // Paper start -+ java.lang.Runnable cleaner1; -+ java.lang.Runnable cleaner2; -+ java.util.concurrent.atomic.AtomicInteger remainingSends = new java.util.concurrent.atomic.AtomicInteger(0); -+ -+ public void onPacketDispatch(net.minecraft.server.level.ServerPlayer player) { -+ remainingSends.incrementAndGet(); -+ } -+ -+ public void onPacketDispatchFinish(net.minecraft.server.level.ServerPlayer player, io.netty.channel.ChannelFuture future) { -+ if (remainingSends.decrementAndGet() <= 0) { -+ // incase of any race conditions, schedule this delayed -+ net.minecraft.server.MCUtil.scheduleTask(5, () -> { -+ if (remainingSends.get() == 0) { -+ cleaner1.run(); -+ cleaner2.run(); -+ } -+ }, "Light Packet Release"); -+ } -+ } -+ // Paper end - - public ClientboundLightUpdatePacketData(ChunkPos pos, LevelLightEngine lightProvider, @Nullable BitSet skyBits, @Nullable BitSet blockBits, boolean nonEdge) { - this.trustEdges = nonEdge; -@@ -26,8 +47,8 @@ public class ClientboundLightUpdatePacketData { - this.blockYMask = new BitSet(); - this.emptySkyYMask = new BitSet(); - this.emptyBlockYMask = new BitSet(); -- this.skyUpdates = Lists.newArrayList(); -- this.blockUpdates = Lists.newArrayList(); -+ this.skyUpdates = Lists.newArrayList();this.cleaner1 = net.minecraft.server.MCUtil.registerListCleaner(this, this.skyUpdates, DataLayer::releaseBytes); // Paper -+ this.blockUpdates = Lists.newArrayList();this.cleaner2 = net.minecraft.server.MCUtil.registerListCleaner(this, this.blockUpdates, DataLayer::releaseBytes); // Paper - - for(int i = 0; i < lightProvider.getLightSectionCount(); ++i) { - if (skyBits == null || skyBits.get(i)) { -@@ -72,7 +93,7 @@ public class ClientboundLightUpdatePacketData { - uninitialized.set(y); - } else { - initialized.set(y); -- nibbles.add((byte[])dataLayer.getData().clone()); -+ nibbles.add((byte[])dataLayer.getCloneIfSet()); // Paper - } - } - -diff --git a/src/main/java/net/minecraft/world/level/chunk/DataLayer.java b/src/main/java/net/minecraft/world/level/chunk/DataLayer.java -index 81701abd11fbc4671393a76a42973f53835ca234..e8cf0088e94925934acd02ba05b9411bd7cf186e 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/DataLayer.java -+++ b/src/main/java/net/minecraft/world/level/chunk/DataLayer.java -@@ -13,11 +13,65 @@ public final class DataLayer { - private static final int NIBBLE_SIZE = 4; - @Nullable - protected byte[] data; -+ // Paper start -+ public static byte[] EMPTY_NIBBLE = new byte[2048]; -+ private static final int nibbleBucketSizeMultiplier = Integer.getInteger("Paper.nibbleBucketSize", 3072); -+ private static final int maxPoolSize = Integer.getInteger("Paper.maxNibblePoolSize", (int) Math.min(6, Math.max(1, Runtime.getRuntime().maxMemory() / 1024 / 1024 / 1024)) * (nibbleBucketSizeMultiplier * 8)); -+ public static final com.destroystokyo.paper.util.pooled.PooledObjects<byte[]> BYTE_2048 = new com.destroystokyo.paper.util.pooled.PooledObjects<>(() -> new byte[2048], maxPoolSize); -+ public static void releaseBytes(byte[] bytes) { -+ if (bytes != null && bytes != EMPTY_NIBBLE && bytes.length == 2048) { -+ System.arraycopy(EMPTY_NIBBLE, 0, bytes, 0, 2048); -+ BYTE_2048.release(bytes); -+ } -+ } - -+ public DataLayer markPoolSafe(byte[] bytes) { -+ if (bytes != EMPTY_NIBBLE) this.data = bytes; -+ return markPoolSafe(); -+ } -+ public DataLayer markPoolSafe() { -+ poolSafe = true; -+ return this; -+ } -+ public byte[] getIfSet() { -+ return this.data != null ? this.data : EMPTY_NIBBLE; -+ } -+ public byte[] getCloneIfSet() { -+ if (data == null) { -+ return EMPTY_NIBBLE; -+ } -+ byte[] ret = BYTE_2048.acquire(); -+ System.arraycopy(getIfSet(), 0, ret, 0, 2048); -+ return ret; -+ } -+ -+ public DataLayer cloneAndSet(byte[] bytes) { -+ if (bytes != null && bytes != EMPTY_NIBBLE) { -+ this.data = BYTE_2048.acquire(); -+ System.arraycopy(bytes, 0, this.data, 0, 2048); -+ } -+ return this; -+ } -+ boolean poolSafe = false; -+ public java.lang.Runnable cleaner; -+ private void registerCleaner() { -+ if (!poolSafe) { -+ cleaner = net.minecraft.server.MCUtil.registerCleaner(this, this.data, DataLayer::releaseBytes); -+ } else { -+ cleaner = net.minecraft.server.MCUtil.once(() -> DataLayer.releaseBytes(this.data)); -+ } -+ } - public DataLayer() {} - - public DataLayer(byte[] bytes) { -+ // Paper start -+ this(bytes, false); -+ } -+ public DataLayer(byte[] bytes, boolean isSafe) { - this.data = bytes; -+ if (!isSafe) this.data = getCloneIfSet(); // Paper - clone for safety -+ registerCleaner(); -+ // Paper end - if (bytes.length != 2048) { - throw (IllegalArgumentException) Util.pauseInIde(new IllegalArgumentException("DataLayer should be 2048 bytes not: " + bytes.length)); - } -@@ -52,7 +106,8 @@ public final class DataLayer { - - private void set(int index, int value) { - if (this.data == null) { -- this.data = new byte[2048]; -+ this.data = BYTE_2048.acquire(); // Paper -+ registerCleaner(); // Paper - } - - int k = DataLayer.getByteIndex(index); -@@ -74,13 +129,33 @@ public final class DataLayer { - public byte[] getData() { - if (this.data == null) { - this.data = new byte[2048]; -+ } else { // Paper start -+ // Accessor may need this object past garbage collection so need to clone it and return pooled value -+ // If we know its safe for pre GC access, use asBytesPoolSafe(). If you just need read, use getIfSet() -+ Runnable cleaner = this.cleaner; -+ if (cleaner != null) { -+ this.data = this.data.clone(); -+ cleaner.run(); // release the previously pooled value -+ this.cleaner = null; -+ } - } -+ // Paper end - - return this.data; - } - -+ @javax.annotation.Nonnull -+ public byte[] asBytesPoolSafe() { -+ if (this.data == null) { -+ this.data = BYTE_2048.acquire(); // Paper -+ registerCleaner(); // Paper -+ } -+ -+ return this.data; -+ } -+ // Paper end - public DataLayer copy() { -- return this.data == null ? new DataLayer() : new DataLayer((byte[]) this.data.clone()); -+ return this.data == null ? new DataLayer() : new DataLayer(this.data); // Paper - clone in ctor - } - - public String toString() { -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -index 980c784b8e5365b62cbeef7f32af9f4383cc01e6..46beea026eec707c69194da6d1d51dc66b61f54e 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -@@ -502,11 +502,11 @@ public class ChunkSerializer { - } - - if (nibblearray != null && !nibblearray.isEmpty()) { -- nbttagcompound1.putByteArray("BlockLight", nibblearray.getData()); -+ nbttagcompound1.putByteArray("BlockLight", nibblearray.asBytesPoolSafe().clone()); // Paper - } - - if (nibblearray1 != null && !nibblearray1.isEmpty()) { -- nbttagcompound1.putByteArray("SkyLight", nibblearray1.getData()); -+ nbttagcompound1.putByteArray("SkyLight", nibblearray1.asBytesPoolSafe().clone()); // Paper - } - - if (!nbttagcompound1.isEmpty()) { -diff --git a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java -index f357a3473682c2d37a20fb862522c67b9979402a..52682471adc13dffc0383fc4abacbd3397f3bb10 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java -+++ b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java -@@ -34,7 +34,9 @@ public abstract class DataLayerStorageMap<M extends DataLayerStorageMap<M>> { - - public void copyDataLayer(long pos) { - if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data -- this.data.queueUpdate(pos, ((DataLayer) this.data.getUpdating(pos)).copy()); // Paper - avoid copying light data -+ DataLayer updating = this.data.getUpdating(pos); // Paper - pool nibbles -+ this.data.queueUpdate(pos, new DataLayer().markPoolSafe(updating.getCloneIfSet())); // Paper - avoid copying light data - pool safe clone -+ if (updating.cleaner != null) net.minecraft.server.MCUtil.scheduleTask(2, updating.cleaner, "Light Engine Release"); // Paper - delay clean incase anything holding ref was still using it - this.clearCache(); - } - -diff --git a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java -index 4f7b63f2cc8a69fa8efb3a84f6abc3d3dcf05b49..cae559b37b5404851fa99d1d206232b5e7ab770c 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java -@@ -157,7 +157,7 @@ public abstract class LayerLightSectionStorage<M extends DataLayerStorageMap<M>> - - protected DataLayer createDataLayer(long sectionPos) { - DataLayer dataLayer = this.queuedSections.get(sectionPos); -- return dataLayer != null ? dataLayer : new DataLayer(); -+ return dataLayer != null ? dataLayer : new DataLayer().markPoolSafe(); // Paper - } - - protected void clearQueuedSectionBlocks(LayerLightEngine<?, ?> storage, long sectionPos) { -@@ -318,12 +318,12 @@ public abstract class LayerLightSectionStorage<M extends DataLayerStorageMap<M>> - - protected void queueSectionData(long sectionPos, @Nullable DataLayer array, boolean nonEdge) { - if (array != null) { -- this.queuedSections.put(sectionPos, array); -+ DataLayer remove = this.queuedSections.put(sectionPos, array); if (remove != null && remove.cleaner != null) remove.cleaner.run(); // Paper - clean up when removed - if (!nonEdge) { - this.untrustedSections.add(sectionPos); - } - } else { -- this.queuedSections.remove(sectionPos); -+ DataLayer remove = this.queuedSections.remove(sectionPos); if (remove != null && remove.cleaner != null) remove.cleaner.run(); // Paper - clean up when removed - } - - } -diff --git a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java -index 9797254e981d08d3934f7ca8f369dd78a6ef1a48..4012d87dc27c3b1096fdaa60bfdfd68f27a22da7 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java -+++ b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java -@@ -163,14 +163,14 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage<SkyLightSec - - return repeatFirstLayer(dataLayer2); - } else { -- return new DataLayer(); -+ return new DataLayer().markPoolSafe(); // Paper - mark pool use as safe (no auto cleaner) - } - } - } - - private static DataLayer repeatFirstLayer(DataLayer source) { - if (source.isEmpty()) { -- return new DataLayer(); -+ return new DataLayer().markPoolSafe(); // Paper - mark pool use as safe (no auto cleaner) - } else { - byte[] bs = source.getData(); - byte[] cs = new byte[2048]; -@@ -179,7 +179,7 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage<SkyLightSec - System.arraycopy(bs, 0, cs, i * 128, 128); - } - -- return new DataLayer(cs); -+ return new DataLayer(cs).markPoolSafe(cs); // Paper - mark pool use as safe (no auto cleaner) - } - } - -@@ -197,7 +197,7 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage<SkyLightSec - this.updatingSectionData.copyDataLayer(l); - } - -- Arrays.fill(this.getDataLayer(l, true).getData(), (byte)-1); -+ Arrays.fill(this.getDataLayer(l, true).asBytesPoolSafe(), (byte)-1); // Paper - int j = SectionPos.sectionToBlockCoord(SectionPos.x(l)); - int k = SectionPos.sectionToBlockCoord(SectionPos.y(l)); - int m = SectionPos.sectionToBlockCoord(SectionPos.z(l)); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -index 7bc1219523eeb0880493e6fb42692f1fdb30c110..187366c33c86b220581c3deac9168d6b6a2c5a3e 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -@@ -339,14 +339,14 @@ public class CraftChunk implements Chunk { - sectionSkyLights[i] = CraftChunk.emptyLight; - } else { - sectionSkyLights[i] = new byte[2048]; -- System.arraycopy(skyLightArray.getData(), 0, sectionSkyLights[i], 0, 2048); -+ System.arraycopy(skyLightArray.getIfSet(), 0, sectionSkyLights[i], 0, 2048); // Paper - } - DataLayer emitLightArray = lightengine.getLayerListener(LightLayer.BLOCK).getDataLayerData(SectionPos.of(x, i, z)); - if (emitLightArray == null) { - sectionEmitLights[i] = CraftChunk.emptyLight; - } else { - sectionEmitLights[i] = new byte[2048]; -- System.arraycopy(emitLightArray.getData(), 0, sectionEmitLights[i], 0, 2048); -+ System.arraycopy(emitLightArray.getIfSet(), 0, sectionEmitLights[i], 0, 2048); // Paper - } - - if (biome != null) { |