From ed8ebbc98a53158d8e4cb19de3774981fed6bd6f Mon Sep 17 00:00:00 2001 From: Aikar Date: Tue, 8 Mar 2016 19:31:47 -0500 Subject: [PATCH] Improve NavigationListener patches. reduces diff and cleans up implementation of goals greatly. --- ...tch => Optimize-Navigation-Listener.patch} | 95 ++++++++++--------- .../Optimize-NavigationListener.patch | 46 --------- 2 files changed, 48 insertions(+), 93 deletions(-) rename Spigot-Server-Patches/{Optimize-NavigationListener-Iteration.patch => Optimize-Navigation-Listener.patch} (51%) delete mode 100644 Spigot-Server-Patches/Optimize-NavigationListener.patch diff --git a/Spigot-Server-Patches/Optimize-NavigationListener-Iteration.patch b/Spigot-Server-Patches/Optimize-Navigation-Listener.patch similarity index 51% rename from Spigot-Server-Patches/Optimize-NavigationListener-Iteration.patch rename to Spigot-Server-Patches/Optimize-Navigation-Listener.patch index a7124fef16..5b2d38a9bf 100644 --- a/Spigot-Server-Patches/Optimize-NavigationListener-Iteration.patch +++ b/Spigot-Server-Patches/Optimize-Navigation-Listener.patch @@ -1,14 +1,22 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Aikar -Date: Mon, 7 Mar 2016 22:43:26 -0500 -Subject: [PATCH] Optimize NavigationListener Iteration +Date: Tue, 8 Mar 2016 19:13:54 -0500 +Subject: [PATCH] Optimize Navigation Listener -I don't know what the person who wrote that code was smoking, but I -don't think it was good. +Mojang was abusing a WeakHashMap to do clean up. However this has some +scary object life concerns as you could have a NavigationListener being +ticked even after the entity it was bound to was removed from world. -Gets rid of the WeakHashMap that mojang was abusing purely to be lazy -on clean up, and handles registering and deregistering navigation -upon world add/remove operations. +Switching this to an Array List gives superior iteration performance +at a slight cost to removal performance. + +Additionally, change listener registration to be done upon world add +instead of immediate up creation. + +This provides benefit of only registering and ticking REAL Navigation +objects, and not invalid entities (cancelled entity spawns for example) + +Gives us a much leaner NavigationListener list. diff --git a/src/main/java/net/minecraft/server/NavigationAbstract.java b/src/main/java/net/minecraft/server/NavigationAbstract.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 @@ -19,7 +27,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 this.g = entityinsentient.getAttributeInstance(GenericAttributes.FOLLOW_RANGE); this.s = this.a(); - this.b.C().a(this); -+ //this.b.C().a(this); // Paper ++ //this.b.C().a(this); // Paper - Optimized Nav Listener - registered on world add } protected abstract Pathfinder a(); @@ -42,57 +50,50 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public NavigationListener() {} -+ public void a(NavigationAbstract navigationabstract) { - this.b.put(navigationabstract, NavigationListener.a); -+ this.add(navigationabstract); // Paper ++ //this.b.put(navigationabstract, NavigationListener.a); // Paper ++ System.err.println("Unexpected NavigationListener add"); // Paper } -+ // Paper start -+ public void add(NavigationAbstract navigationabstract) { -+ this.navigators.add(navigationabstract); -+ } -+ public void remove(NavigationAbstract navigationabstract) { -+ this.navigators.remove(navigationabstract); -+ } -+ // Paper end -+ public void a(World world, BlockPosition blockposition, IBlockData iblockdata, IBlockData iblockdata1, int i) { if (this.a(world, blockposition, iblockdata, iblockdata1)) { -- NavigationAbstract[] anavigationabstract = (NavigationAbstract[]) this.b.keySet().toArray(new NavigationAbstract[0]); -- NavigationAbstract[] anavigationabstract1 = anavigationabstract; -- int j = anavigationabstract.length; -+ // Paper start -+ //NavigationAbstract[] anavigationabstract = (NavigationAbstract[]) this.navigators.keySet().toArray(new NavigationAbstract[0]); -+ //NavigationAbstract[] anavigationabstract1 = anavigationabstract; -+ int j = this.navigators.size(); -+ ++ /* // Paper start + NavigationAbstract[] anavigationabstract = (NavigationAbstract[]) this.b.keySet().toArray(new NavigationAbstract[0]); + NavigationAbstract[] anavigationabstract1 = anavigationabstract; + int j = anavigationabstract.length; - for (int k = 0; k < j; ++k) { +- for (int k = 0; k < j; ++k) { - NavigationAbstract navigationabstract = anavigationabstract1[k]; ++ */ ++ for (int k = 0; k < this.navigators.size(); ++k) { + NavigationAbstract navigationabstract = this.navigators.get(k); + // Paper end if (navigationabstract != null && !navigationabstract.i()) { PathEntity pathentity = navigationabstract.k(); -diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/World.java -+++ b/src/main/java/net/minecraft/server/World.java -@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { - this.getChunkAt(i, j).a(entity); - this.entityList.add(entity); - this.b(entity); -+ if (entity instanceof EntityInsentient) { this.getNavListener().add(((EntityInsentient) entity).navigation); } // Paper - return true; - } - } -@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { - } - // CraftBukkit end - } // Spigot -+ if (entity instanceof EntityInsentient) { this.getNavListener().remove(((EntityInsentient) entity).navigation); } // Paper - this.c(entity); - } +@@ -0,0 +0,0 @@ public class NavigationListener implements IWorldAccess { + + public void a(int i, boolean flag, double d0, double d1, double d2, double d3, double d4, double d5, int... aint) {} + +- public void a(Entity entity) {} ++ public void a(Entity entity) { ++ // Paper start ++ if (entity instanceof EntityInsentient) { ++ this.navigators.add(((EntityInsentient) entity).navigation); ++ } ++ // Paper end ++ } + +- public void b(Entity entity) {} ++ public void b(Entity entity) { ++ // Paper start ++ if (entity instanceof EntityInsentient) { ++ this.navigators.remove(((EntityInsentient) entity).navigation); ++ } ++ // Paper end ++ } + + public void a(SoundEffect soundeffect, BlockPosition blockposition) {} -- \ No newline at end of file diff --git a/Spigot-Server-Patches/Optimize-NavigationListener.patch b/Spigot-Server-Patches/Optimize-NavigationListener.patch deleted file mode 100644 index 527f9b31df..0000000000 --- a/Spigot-Server-Patches/Optimize-NavigationListener.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 7 Mar 2016 20:41:27 -0500 -Subject: [PATCH] Optimize NavigationListener - -I believe Mojang intended to call the NavigationListener Block Update -method anytime a block is changed, but accidently added it for every -block physics event instead. - -This code is massively ineffecient, and physics is so super hot, it -destroys server performance. - -This patch moves the block update call to setTypeAndData instead of -on Physics. - -diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/World.java -+++ b/src/main/java/net/minecraft/server/World.java -@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { - private int K; - public final Random random = new Random(); - public WorldProvider worldProvider; -- protected NavigationListener t = new NavigationListener(); -+ protected NavigationListener t = new NavigationListener(); public NavigationListener getNavListener() { return this.t; } // Paper - protected List u; - protected IChunkProvider chunkProvider; - protected final IDataManager dataManager; -@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { - this.ticksPerAnimalSpawns = this.getServer().getTicksPerAnimalSpawns(); // CraftBukkit - this.ticksPerMonsterSpawns = this.getServer().getTicksPerMonsterSpawns(); // CraftBukkit - // CraftBukkit end -- this.u = Lists.newArrayList(new IWorldAccess[] { this.t}); -+ this.u = Lists.newArrayList(new IWorldAccess[] {}); // Paper - this.L = Calendar.getInstance(); - this.scoreboard = new Scoreboard(); - this.allowMonsters = true; -@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { - if (!this.captureBlockStates) { // Don't notify clients or update physics while capturing blockstates - // Modularize client and physic updates - notifyAndUpdatePhysics(blockposition, chunk, iblockdata1, iblockdata, i); -+ this.getNavListener().a(this, blockposition, iblockdata1, iblockdata, i); // Paper - } - // CraftBukkit end - --- \ No newline at end of file