Merge pull request #66 from starlis/improvNav

Improve NavigationListener patches.
This commit is contained in:
Zach Brown 2016-03-08 20:14:07 -06:00
commit d995d003f4
2 changed files with 48 additions and 93 deletions

View file

@ -1,14 +1,22 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co> From: Aikar <aikar@aikar.co>
Date: Mon, 7 Mar 2016 22:43:26 -0500 Date: Tue, 8 Mar 2016 19:13:54 -0500
Subject: [PATCH] Optimize NavigationListener Iteration Subject: [PATCH] Optimize Navigation Listener
I don't know what the person who wrote that code was smoking, but I Mojang was abusing a WeakHashMap to do clean up. However this has some
don't think it was good. 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 Switching this to an Array List gives superior iteration performance
on clean up, and handles registering and deregistering navigation at a slight cost to removal performance.
upon world add/remove operations.
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 diff --git a/src/main/java/net/minecraft/server/NavigationAbstract.java b/src/main/java/net/minecraft/server/NavigationAbstract.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
@ -19,7 +27,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
this.g = entityinsentient.getAttributeInstance(GenericAttributes.FOLLOW_RANGE); this.g = entityinsentient.getAttributeInstance(GenericAttributes.FOLLOW_RANGE);
this.s = this.a(); this.s = this.a();
- this.b.C().a(this); - 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(); protected abstract Pathfinder a();
@ -42,57 +50,50 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public NavigationListener() {} public NavigationListener() {}
+
public void a(NavigationAbstract navigationabstract) { public void a(NavigationAbstract navigationabstract) {
- this.b.put(navigationabstract, NavigationListener.a); - 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) { public void a(World world, BlockPosition blockposition, IBlockData iblockdata, IBlockData iblockdata1, int i) {
if (this.a(world, blockposition, iblockdata, iblockdata1)) { if (this.a(world, blockposition, iblockdata, iblockdata1)) {
- NavigationAbstract[] anavigationabstract = (NavigationAbstract[]) this.b.keySet().toArray(new NavigationAbstract[0]); + /* // Paper start
- NavigationAbstract[] anavigationabstract1 = anavigationabstract; NavigationAbstract[] anavigationabstract = (NavigationAbstract[]) this.b.keySet().toArray(new NavigationAbstract[0]);
- int j = anavigationabstract.length; NavigationAbstract[] anavigationabstract1 = anavigationabstract;
+ // Paper start int j = anavigationabstract.length;
+ //NavigationAbstract[] anavigationabstract = (NavigationAbstract[]) this.navigators.keySet().toArray(new NavigationAbstract[0]);
+ //NavigationAbstract[] anavigationabstract1 = anavigationabstract;
+ int j = this.navigators.size();
+
for (int k = 0; k < j; ++k) { - for (int k = 0; k < j; ++k) {
- NavigationAbstract navigationabstract = anavigationabstract1[k]; - NavigationAbstract navigationabstract = anavigationabstract1[k];
+ */
+ for (int k = 0; k < this.navigators.size(); ++k) {
+ NavigationAbstract navigationabstract = this.navigators.get(k); + NavigationAbstract navigationabstract = this.navigators.get(k);
+ // Paper end + // Paper end
if (navigationabstract != null && !navigationabstract.i()) { if (navigationabstract != null && !navigationabstract.i()) {
PathEntity pathentity = navigationabstract.k(); PathEntity pathentity = navigationabstract.k();
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java @@ -0,0 +0,0 @@ public class NavigationListener implements IWorldAccess {
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/World.java public void a(int i, boolean flag, double d0, double d1, double d2, double d3, double d4, double d5, int... aint) {}
+++ b/src/main/java/net/minecraft/server/World.java
@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess { - public void a(Entity entity) {}
this.getChunkAt(i, j).a(entity); + public void a(Entity entity) {
this.entityList.add(entity); + // Paper start
this.b(entity); + if (entity instanceof EntityInsentient) {
+ if (entity instanceof EntityInsentient) { this.getNavListener().add(((EntityInsentient) entity).navigation); } // Paper + this.navigators.add(((EntityInsentient) entity).navigation);
return true; + }
} + // Paper end
} + }
@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess {
} - public void b(Entity entity) {}
// CraftBukkit end + public void b(Entity entity) {
} // Spigot + // Paper start
+ if (entity instanceof EntityInsentient) { this.getNavListener().remove(((EntityInsentient) entity).navigation); } // Paper + if (entity instanceof EntityInsentient) {
this.c(entity); + this.navigators.remove(((EntityInsentient) entity).navigation);
} + }
+ // Paper end
+ }
public void a(SoundEffect soundeffect, BlockPosition blockposition) {}
-- --

View file

@ -1,46 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
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<IWorldAccess> 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
--