Mirror von
https://github.com/PaperMC/Paper.git
synchronisiert 2024-11-15 12:30:06 +01:00
ce270e1412
Upstream has released updates that appears to apply and compile correctly. This update has not been tested by PaperMC and as with ANY update, please do your own testing Bukkit Changes: b2f1908c SPIGOT-5783: Add helpful info to UnknownDependencyException e4f46260 SPIGOT-2623: Add EntityEquipment methods to get/set ItemStacks by slot. 529a9a69 SPIGOT-5751: Clarify behaviour of block drop-related API methods CraftBukkit Changes:8ea9b138
Remove outdated build delay.ffc2b251
Revert "#675: Fix redirected CommandNodes sometimes not being properly redirected"cb701f6b
#675: Fix redirected CommandNodes sometimes not being properly redirectedc9d7c16b
SPIGOT-2623: Add EntityEquipment methods to get/set ItemStacks by slot.fad2494a
#673: Fix Craftworld#isChunkLoaded8637ec00
SPIGOT-5751: Made breakNaturally and getDrops returns the correct item if no argument is given Spigot Changes: a99063f7 Rebuild patches Fixes #3602
128 Zeilen
6.6 KiB
Diff
128 Zeilen
6.6 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Aikar <aikar@aikar.co>
|
|
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 71d2ae2a9c5a05351241b5a313e66ca15b0624ef..232b0023773008c19f19ad4658eb40fcd08c0333 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 e641d4b8d8b4ac5d539e6d9c0eaf345601e0b499..4b3e632a8944828189bc8a5dada32913c1929286 100644
|
|
--- a/src/main/java/net/minecraft/server/VoxelShapes.java
|
|
+++ b/src/main/java/net/minecraft/server/VoxelShapes.java
|
|
@@ -319,9 +319,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);
|
|
@@ -331,7 +343,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 {
|