From 2f8bdbfde84cea2e385aad576ca466c3516db0be Mon Sep 17 00:00:00 2001 From: Aikar Date: Thu, 28 Feb 2019 01:35:06 -0500 Subject: [PATCH] Fix BlockState hashCode optimization patch performance bug we missed something in updating this patch and accidently left hashCode as a 0 value. This caused a pretty nasty performance hit for BlockStateEnum instances as they would be all a hash collision. This update fixes that and also promotes the optimizations to cover ALL cases of Block States, not just enums. While mojang cached hashCode in 1.13, we can still just use a simple large prime based hashCode that auto increments guaranteeing no overlap. Additionally, replace all equals with an identity check. --- ...ptimise-BlockState-s-hashCode-equals.patch | 84 +++++++++++++++++++ ...e-BlockStateEnum-hashCode-and-equals.patch | 62 -------------- 2 files changed, 84 insertions(+), 62 deletions(-) create mode 100644 Spigot-Server-Patches/0130-Optimise-BlockState-s-hashCode-equals.patch delete mode 100644 Spigot-Server-Patches/0130-Optimise-BlockStateEnum-hashCode-and-equals.patch diff --git a/Spigot-Server-Patches/0130-Optimise-BlockState-s-hashCode-equals.patch b/Spigot-Server-Patches/0130-Optimise-BlockState-s-hashCode-equals.patch new file mode 100644 index 0000000000..e751d8038f --- /dev/null +++ b/Spigot-Server-Patches/0130-Optimise-BlockState-s-hashCode-equals.patch @@ -0,0 +1,84 @@ +From 63f4233aa49d41ab53a84ebd6a20d8d10449855f Mon Sep 17 00:00:00 2001 +From: Alfie Cleveland +Date: Fri, 19 Aug 2016 01:52:56 +0100 +Subject: [PATCH] Optimise BlockState's hashCode/equals + +These are singleton "single instance" objects. We can rely on +object identity checks safely. + +Use a simpler optimized hashcode + +diff --git a/src/main/java/net/minecraft/server/BlockState.java b/src/main/java/net/minecraft/server/BlockState.java +index d95c0955a9..ea0e0ff4fe 100644 +--- a/src/main/java/net/minecraft/server/BlockState.java ++++ b/src/main/java/net/minecraft/server/BlockState.java +@@ -26,23 +26,13 @@ public abstract class BlockState> implements IBlockState + } + + public boolean equals(Object object) { +- if (this == object) { +- return true; +- } else if (!(object instanceof BlockState)) { +- return false; +- } else { +- BlockState blockstate = (BlockState) object; +- +- return this.a.equals(blockstate.a) && this.b.equals(blockstate.b); +- } ++ return this == object; // Paper - only one instance per configuration + } + ++ private static java.util.concurrent.atomic.AtomicInteger hashId = new java.util.concurrent.atomic.AtomicInteger(1);// Paper - only one instance per configuration ++ private final int hashCode = 92821 * hashId.getAndIncrement(); // Paper - only one instance per configuration + public final int hashCode() { +- if (this.c == null) { +- this.c = this.c(); +- } +- +- return this.c; ++ return hashCode; // Paper - only one instance per configuration + } + + public int c() { +diff --git a/src/main/java/net/minecraft/server/BlockStateBoolean.java b/src/main/java/net/minecraft/server/BlockStateBoolean.java +index 4c1d39d67c..71d2ad9703 100644 +--- a/src/main/java/net/minecraft/server/BlockStateBoolean.java ++++ b/src/main/java/net/minecraft/server/BlockStateBoolean.java +@@ -28,7 +28,7 @@ public class BlockStateBoolean extends BlockState { + return obool.toString(); + } + +- public boolean equals(Object object) { ++ public boolean equals_unused(Object object) { // Paper + if (this == object) { + return true; + } else if (object instanceof BlockStateBoolean && super.equals(object)) { +diff --git a/src/main/java/net/minecraft/server/BlockStateEnum.java b/src/main/java/net/minecraft/server/BlockStateEnum.java +index 986b9ccea8..facbf30b4e 100644 +--- a/src/main/java/net/minecraft/server/BlockStateEnum.java ++++ b/src/main/java/net/minecraft/server/BlockStateEnum.java +@@ -47,7 +47,7 @@ public class BlockStateEnum & INamable> extends BlockState + return ((INamable) t0).getName(); + } + +- public boolean equals(Object object) { ++ public boolean equals_unused(Object object) { // Paper + if (this == object) { + return true; + } else if (object instanceof BlockStateEnum && super.equals(object)) { +diff --git a/src/main/java/net/minecraft/server/BlockStateInteger.java b/src/main/java/net/minecraft/server/BlockStateInteger.java +index 2f12e15e07..613cd0bce2 100644 +--- a/src/main/java/net/minecraft/server/BlockStateInteger.java ++++ b/src/main/java/net/minecraft/server/BlockStateInteger.java +@@ -37,7 +37,7 @@ public class BlockStateInteger extends BlockState { + return this.a; + } + +- public boolean equals(Object object) { ++ public boolean equals_unused(Object object) { // Paper + if (this == object) { + return true; + } else if (object instanceof BlockStateInteger && super.equals(object)) { +-- +2.20.1 + diff --git a/Spigot-Server-Patches/0130-Optimise-BlockStateEnum-hashCode-and-equals.patch b/Spigot-Server-Patches/0130-Optimise-BlockStateEnum-hashCode-and-equals.patch deleted file mode 100644 index 3a1285d026..0000000000 --- a/Spigot-Server-Patches/0130-Optimise-BlockStateEnum-hashCode-and-equals.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 7064b8b9f50b18bbd81ed129577c4944104ad7d9 Mon Sep 17 00:00:00 2001 -From: Alfie Cleveland -Date: Fri, 19 Aug 2016 01:52:56 +0100 -Subject: [PATCH] Optimise BlockStateEnum hashCode and equals - - -diff --git a/src/main/java/net/minecraft/server/BlockStateEnum.java b/src/main/java/net/minecraft/server/BlockStateEnum.java -index 986b9ccea..259da0aa0 100644 ---- a/src/main/java/net/minecraft/server/BlockStateEnum.java -+++ b/src/main/java/net/minecraft/server/BlockStateEnum.java -@@ -9,6 +9,7 @@ import java.util.Collection; - import java.util.Iterator; - import java.util.Map; - import java.util.Optional; -+import java.util.concurrent.atomic.AtomicInteger; - import java.util.function.Predicate; - import java.util.stream.Collectors; - -@@ -17,6 +18,11 @@ public class BlockStateEnum & INamable> extends BlockState - private final ImmutableSet a; - private final Map b = Maps.newHashMap(); - -+ // Paper start - BlockStateEnum is a singleton, so we can use our own hashCode -+ private static AtomicInteger hashId = new AtomicInteger(1); -+ private int hashCode; -+ // Paper end -+ - protected BlockStateEnum(String s, Class oclass, Collection collection) { - super(s, oclass); - this.a = ImmutableSet.copyOf(collection); -@@ -47,24 +53,14 @@ public class BlockStateEnum & INamable> extends BlockState - return ((INamable) t0).getName(); - } - -+ @Override // Paper start - override equals as BlockStateEnum is a singleton - public boolean equals(Object object) { -- if (this == object) { -- return true; -- } else if (object instanceof BlockStateEnum && super.equals(object)) { -- BlockStateEnum blockstateenum = (BlockStateEnum) object; -- -- return this.a.equals(blockstateenum.a) && this.b.equals(blockstateenum.b); -- } else { -- return false; -- } -+ return this == object; -+ // Paper end - override equals as BlockStateEnum is a singleton - } - - public int c() { -- int i = super.c(); -- -- i = 31 * i + this.a.hashCode(); -- i = 31 * i + this.b.hashCode(); -- return i; -+ return hashCode; // Paper - hashCode method is final, but we can do this here - } - - public static & INamable> BlockStateEnum of(String s, Class oclass) { --- -2.20.1 -