diff --git a/Spigot-Server-Patches/0499-Optimize-Voxel-Shape-Merging.patch b/Spigot-Server-Patches/0499-Optimize-Voxel-Shape-Merging.patch new file mode 100644 index 0000000000..d9624a5489 --- /dev/null +++ b/Spigot-Server-Patches/0499-Optimize-Voxel-Shape-Merging.patch @@ -0,0 +1,130 @@ +From fc80e192e73525b7ac69affa6b4c586fa039cef4 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 3 May 2020 22:35:09 -0400 +Subject: [PATCH] Optimize Voxel Shape Merging + +This method shows up as super hot in profiler, and also a high "self" time. + +Upon analyzing, it appears most usages of this method fall down to the final +else statement of the nasty ternary. + +Upon even further analyzation, it appears then the majority of those have a +consistent list 1.... One with Infinity head and Tails. + +First optimization is to detect these infinite states and immediately return that +VoxelShapeMergerList so we can avoid testing the rest for most cases. + +Break the method into 2 to help the JVM promote inlining of this fast path. + +Then it was also noticed that VoxelShapeMergerList constructor is also a hotspot +with a high self time... + +Well, knowing that in most cases our list 1 is actualy the same value, it allows +us to know that with an infinite list1, the result on the merger is essentially +list2 as the final values. + +This let us analyze the 2 potential states (Infinite with 2 sources or 4 sources) +and compute a deterministic result for the MergerList values. + +Additionally, this lets us avoid even allocating new objects for this too, further +reducing memory usage. + +diff --git a/src/main/java/net/minecraft/server/VoxelShapeMergerList.java b/src/main/java/net/minecraft/server/VoxelShapeMergerList.java +index 71d2ae2a9c..232b002377 100644 +--- a/src/main/java/net/minecraft/server/VoxelShapeMergerList.java ++++ b/src/main/java/net/minecraft/server/VoxelShapeMergerList.java +@@ -6,10 +6,16 @@ import it.unimi.dsi.fastutil.ints.IntArrayList; + + public final class VoxelShapeMergerList implements VoxelShapeMerger { + +- private final DoubleArrayList a; ++ private final DoubleList a; // Paper + private final IntArrayList b; + private final IntArrayList c; + ++ // Paper start ++ private static final IntArrayList INFINITE_B_1 = new IntArrayList(new int[]{1, 1}); ++ private static final IntArrayList INFINITE_B_0 = new IntArrayList(new int[]{0, 0}); ++ private static final IntArrayList INFINITE_C = new IntArrayList(new int[]{0, 1}); ++ // Paper end ++ + protected VoxelShapeMergerList(DoubleList doublelist, DoubleList doublelist1, boolean flag, boolean flag1) { + int i = 0; + int j = 0; +@@ -18,6 +24,22 @@ public final class VoxelShapeMergerList implements VoxelShapeMerger { + int l = doublelist1.size(); + int i1 = k + l; + ++ // Paper start - optimize common path of infinity doublelist ++ int size = doublelist.size(); ++ double tail = doublelist.getDouble(size - 1); ++ double head = doublelist.getDouble(0); ++ if (head == Double.NEGATIVE_INFINITY && tail == Double.POSITIVE_INFINITY && !flag && !flag1 && (size == 2 || size == 4)) { ++ this.a = doublelist1; ++ if (size == 2) { ++ this.b = INFINITE_B_0; ++ } else { ++ this.b = INFINITE_B_1; ++ } ++ this.c = INFINITE_C; ++ return; ++ } ++ // Paper end ++ + this.a = new DoubleArrayList(i1); + this.b = new IntArrayList(i1); + this.c = new IntArrayList(i1); +diff --git a/src/main/java/net/minecraft/server/VoxelShapes.java b/src/main/java/net/minecraft/server/VoxelShapes.java +index 08c83c62df..bb3a1a97df 100644 +--- a/src/main/java/net/minecraft/server/VoxelShapes.java ++++ b/src/main/java/net/minecraft/server/VoxelShapes.java +@@ -316,9 +316,21 @@ public final class VoxelShapes { + } + + @VisibleForTesting +- protected static VoxelShapeMerger a(int i, DoubleList doublelist, DoubleList doublelist1, boolean flag, boolean flag1) { ++ private static VoxelShapeMerger a(int i, DoubleList doublelist, DoubleList doublelist1, boolean flag, boolean flag1) { // Paper - private ++ // Paper start - fast track the most common scenario ++ // doublelist is usually a DoubleArrayList with Infinite head/tails that falls to the final else clause ++ // This is actually the most common path, so jump to it straight away ++ if (doublelist.getDouble(0) == Double.NEGATIVE_INFINITY && doublelist.getDouble(doublelist.size() - 1) == Double.POSITIVE_INFINITY) { ++ return new VoxelShapeMergerList(doublelist, doublelist1, flag, flag1); ++ } ++ // Split out rest to hopefully inline the above ++ return lessCommonMerge(i, doublelist, doublelist1, flag, flag1); ++ } ++ ++ private static VoxelShapeMerger lessCommonMerge(int i, DoubleList doublelist, DoubleList doublelist1, boolean flag, boolean flag1) { + int j = doublelist.size() - 1; + int k = doublelist1.size() - 1; ++ // Paper note - Rewrite below as optimized order if instead of nasty ternary + + if (doublelist instanceof VoxelShapeCubePoint && doublelist1 instanceof VoxelShapeCubePoint) { + long l = a(j, k); +@@ -328,7 +340,22 @@ public final class VoxelShapes { + } + } + +- return (VoxelShapeMerger) (doublelist.getDouble(j) < doublelist1.getDouble(0) - 1.0E-7D ? new VoxelShapeMergerDisjoint(doublelist, doublelist1, false) : (doublelist1.getDouble(k) < doublelist.getDouble(0) - 1.0E-7D ? new VoxelShapeMergerDisjoint(doublelist1, doublelist, true) : (j == k && Objects.equals(doublelist, doublelist1) ? (doublelist instanceof VoxelShapeMergerIdentical ? (VoxelShapeMerger) doublelist : (doublelist1 instanceof VoxelShapeMergerIdentical ? (VoxelShapeMerger) doublelist1 : new VoxelShapeMergerIdentical(doublelist))) : new VoxelShapeMergerList(doublelist, doublelist1, flag, flag1)))); ++ // Identical happens more often than Disjoint ++ if (j == k && Objects.equals(doublelist, doublelist1)) { ++ if (doublelist instanceof VoxelShapeMergerIdentical) { ++ return (VoxelShapeMerger) doublelist; ++ } else if (doublelist1 instanceof VoxelShapeMergerIdentical) { ++ return (VoxelShapeMerger) doublelist1; ++ } ++ return new VoxelShapeMergerIdentical(doublelist); ++ } else if (doublelist.getDouble(j) < doublelist1.getDouble(0) - 1.0E-07) { ++ return new VoxelShapeMergerDisjoint(doublelist, doublelist1, false); ++ } else if (doublelist1.getDouble(k) < doublelist.getDouble(0) - 1.0E-07) { ++ return new VoxelShapeMergerDisjoint(doublelist1, doublelist, true); ++ } else { ++ return new VoxelShapeMergerList(doublelist, doublelist1, flag, flag1); ++ } ++ // Paper end + } + + public interface a { +-- +2.26.2 +