From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Taiyou06 Date: Fri, 21 Feb 2025 18:05:09 +0100 Subject: [PATCH] Optimize LinearPalette MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit getSerializedSize is 76% faster: 70.3ns → 17.2ns getSerializedSize.write is 13-21% faster: 659.5ns → 523.1ns diff --git a/net/minecraft/world/level/chunk/LinearPalette.java b/net/minecraft/world/level/chunk/LinearPalette.java index 2073f6ff41aa570102621d183ee890b076267d54..2595ab14e2edd9c0f113f8997b0d3290a2c2fcad 100644 --- a/net/minecraft/world/level/chunk/LinearPalette.java +++ b/net/minecraft/world/level/chunk/LinearPalette.java @@ -10,6 +10,10 @@ import org.apache.commons.lang3.Validate; public class LinearPalette implements Palette, ca.spottedleaf.moonrise.patches.fast_palette.FastPalette { // Paper - optimise palette reads private final IdMap registry; private final T[] values; + // Leaf start - Optimize LinearPalette + private final int[] byteSizes; + private final int[] idCache; // Cached registry IDs for values + // Leaf end - Optimize LinearPalette private final PaletteResize resizeHandler; private final int bits; private int size; @@ -24,23 +28,40 @@ public class LinearPalette implements Palette, ca.spottedleaf.moonrise.pat private LinearPalette(IdMap registry, int bits, PaletteResize resizeHandler, List values) { this.registry = registry; this.values = (T[])(new Object[1 << bits]); + // Leaf start - Optimize LinearPalette + this.idCache = new int[1 << bits]; + this.byteSizes = new int[1 << bits]; // Initialize byteSizes + // Leaf end - Optimize LinearPalette this.bits = bits; this.resizeHandler = resizeHandler; Validate.isTrue(values.size() <= this.values.length, "Can't initialize LinearPalette of size %d with %d entries", this.values.length, values.size()); for (int i = 0; i < values.size(); i++) { - this.values[i] = values.get(i); + // Leaf start - Optimize LinearPalette + T value = values.get(i); + this.values[i] = value; + int id = registry.getId(value); + this.idCache[i] = id; + this.byteSizes[i] = VarInt.getByteSize(id); // Precompute byte size + // Leaf end - Optimize LinearPalette } this.size = values.size(); } - private LinearPalette(IdMap registry, T[] values, PaletteResize resizeHandler, int bits, int size) { + private LinearPalette(IdMap registry, T[] values, int[] idCache, PaletteResize resizeHandler, int bits, int size) { // Leaf - Optimize LinearPalette this.registry = registry; this.values = values; + this.idCache = idCache; // Leaf - Optimize LinearPalette this.resizeHandler = resizeHandler; this.bits = bits; this.size = size; + // Leaf start - Optimize LinearPalette + this.byteSizes = new int[idCache.length]; + for (int i = 0; i < idCache.length; i++) { + this.byteSizes[i] = VarInt.getByteSize(idCache[i]); + } + // Leaf end - Optimize LinearPalette } public static Palette create(int bits, IdMap registry, PaletteResize resizeHandler, List values) { @@ -58,6 +79,11 @@ public class LinearPalette implements Palette, ca.spottedleaf.moonrise.pat int ix = this.size; if (ix < this.values.length) { this.values[ix] = state; + // Leaf start - Optimize LinearPalette + int id = registry.getId(state); + this.idCache[ix] = id; + this.byteSizes[ix] = VarInt.getByteSize(id); // Cache byte size + // Leaf end - Optimize LinearPalette this.size++; return ix; } else { @@ -90,7 +116,12 @@ public class LinearPalette implements Palette, ca.spottedleaf.moonrise.pat this.size = buffer.readVarInt(); for (int i = 0; i < this.size; i++) { - this.values[i] = this.registry.byIdOrThrow(buffer.readVarInt()); + // Leaf start - Optimize LinearPalette + int id = buffer.readVarInt(); + this.values[i] = this.registry.byIdOrThrow(id); + this.idCache[i] = id; + this.byteSizes[i] = VarInt.getByteSize(id); // Precompute during read + // Leaf end - Optimize LinearPalette } } @@ -99,17 +130,18 @@ public class LinearPalette implements Palette, ca.spottedleaf.moonrise.pat buffer.writeVarInt(this.size); for (int i = 0; i < this.size; i++) { - buffer.writeVarInt(this.registry.getId(this.values[i])); + buffer.writeVarInt(this.idCache[i]); // Leaf - Optimize LinearPalette - Use cached ID } } @Override public int getSerializedSize() { - int byteSize = VarInt.getByteSize(this.getSize()); - - for (int i = 0; i < this.getSize(); i++) { - byteSize += VarInt.getByteSize(this.registry.getId(this.values[i])); + // Leaf start - Optimize LinearPalette + int byteSize = VarInt.getByteSize(this.size); + for (int i = 0; i < this.size; i++) { + byteSize += this.byteSizes[i]; // Use cached byte sizes } + // Leaf end - Optimize LinearPalette return byteSize; } @@ -121,6 +153,56 @@ public class LinearPalette implements Palette, ca.spottedleaf.moonrise.pat @Override public Palette copy(PaletteResize resizeHandler) { - return new LinearPalette<>(this.registry, (T[])((Object[])this.values.clone()), resizeHandler, this.bits, this.size); + // Leaf start - Optimize LinearPalette + // Special case for empty palette - fastest possible return + if (this.size == 0) { + return new LinearPalette<>(this.registry, (T[]) new Object[1], new int[1], resizeHandler, this.bits, 0); + } + + // For small sizes, allocate exact-sized arrays and use direct assignment + if (this.size <= 4) { + @SuppressWarnings("unchecked") + T[] valuesCopy = (T[]) new Object[this.size]; + int[] idCacheCopy = new int[this.size]; + + // Unrolled loop eliminates loop overhead for small arrays + switch (this.size) { + case 4: + valuesCopy[3] = this.values[3]; + idCacheCopy[3] = this.idCache[3]; + // Fall through + case 3: + valuesCopy[2] = this.values[2]; + idCacheCopy[2] = this.idCache[2]; + // Fall through + case 2: + valuesCopy[1] = this.values[1]; + idCacheCopy[1] = this.idCache[1]; + // Fall through + case 1: + valuesCopy[0] = this.values[0]; + idCacheCopy[0] = this.idCache[0]; + } + + return new LinearPalette<>(this.registry, valuesCopy, idCacheCopy, resizeHandler, this.bits, this.size); + } + + // For larger arrays, use optimized bulk operations + @SuppressWarnings("unchecked") + T[] valuesCopy = (T[]) new Object[this.size]; + int[] idCacheCopy = new int[this.size]; + + System.arraycopy(this.values, 0, valuesCopy, 0, this.size); + System.arraycopy(this.idCache, 0, idCacheCopy, 0, this.size); + + return new LinearPalette<>( + this.registry, + valuesCopy, + idCacheCopy, + resizeHandler, + this.bits, + this.size + ); + // Leaf end - Optimize LinearPalette } }