Remove streams from Mob AI System
The streams hurt performance and allocate tons of garbage, so replace them with the standard iterator. Also optimise the stream.anyMatch statement to move to a bitset where we can replace the call with a single bitwise operation.
This commit is contained in:
250
Spigot-Server-Patches/Remove-streams-from-Mob-AI-System.patch
Normal file
250
Spigot-Server-Patches/Remove-streams-from-Mob-AI-System.patch
Normal file
@@ -0,0 +1,250 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <spottedleaf@spottedleaf.dev>
|
||||
Date: Mon, 6 Apr 2020 17:53:29 -0700
|
||||
Subject: [PATCH] Remove streams from Mob AI System
|
||||
|
||||
The streams hurt performance and allocate tons of garbage, so
|
||||
replace them with the standard iterator.
|
||||
|
||||
Also optimise the stream.anyMatch statement to move to a bitset
|
||||
where we can replace the call with a single bitwise operation.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/PathfinderGoal.java b/src/main/java/net/minecraft/server/PathfinderGoal.java
|
||||
index bdb90a3466..134f7d0013 100644
|
||||
--- a/src/main/java/net/minecraft/server/PathfinderGoal.java
|
||||
+++ b/src/main/java/net/minecraft/server/PathfinderGoal.java
|
||||
@@ -0,0 +0,0 @@
|
||||
package net.minecraft.server;
|
||||
|
||||
+import com.destroystokyo.paper.util.set.OptimizedSmallEnumSet; // Paper - remove streams from pathfindergoalselector
|
||||
import java.util.EnumSet;
|
||||
|
||||
public abstract class PathfinderGoal {
|
||||
|
||||
- private final EnumSet<PathfinderGoal.Type> a = EnumSet.noneOf(PathfinderGoal.Type.class);
|
||||
+ private final OptimizedSmallEnumSet<Type> goalTypes = new OptimizedSmallEnumSet<>(PathfinderGoal.Type.class); // Paper - remove streams from pathfindergoalselector
|
||||
|
||||
public PathfinderGoal() {}
|
||||
|
||||
@@ -0,0 +0,0 @@ public abstract class PathfinderGoal {
|
||||
public void e() {}
|
||||
|
||||
public void a(EnumSet<PathfinderGoal.Type> enumset) {
|
||||
- this.a.clear();
|
||||
- this.a.addAll(enumset);
|
||||
+ // Paper start - remove streams from pathfindergoalselector
|
||||
+ this.goalTypes.clear();
|
||||
+ this.goalTypes.addAllUnchecked(enumset);
|
||||
+ // Paper end - remove streams from pathfindergoalselector
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return this.getClass().getSimpleName();
|
||||
}
|
||||
|
||||
- public EnumSet<PathfinderGoal.Type> i() {
|
||||
- return this.a;
|
||||
+ // Paper start - remove streams from pathfindergoalselector
|
||||
+ public com.destroystokyo.paper.util.set.OptimizedSmallEnumSet<PathfinderGoal.Type> getGoalTypes() {
|
||||
+ return this.goalTypes;
|
||||
+ // Paper end - remove streams from pathfindergoalselector
|
||||
}
|
||||
|
||||
public static enum Type {
|
||||
diff --git a/src/main/java/net/minecraft/server/PathfinderGoalSelector.java b/src/main/java/net/minecraft/server/PathfinderGoalSelector.java
|
||||
index 935136771e..90319909e5 100644
|
||||
--- a/src/main/java/net/minecraft/server/PathfinderGoalSelector.java
|
||||
+++ b/src/main/java/net/minecraft/server/PathfinderGoalSelector.java
|
||||
@@ -0,0 +0,0 @@
|
||||
package net.minecraft.server;
|
||||
|
||||
+import com.destroystokyo.paper.util.set.OptimizedSmallEnumSet; // Paper - remove streams from pathfindergoalselector
|
||||
import com.google.common.collect.Sets;
|
||||
import java.util.EnumMap;
|
||||
import java.util.EnumSet;
|
||||
+import java.util.Iterator; // Paper - remove streams from pathfindergoalselector
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
@@ -0,0 +0,0 @@ public class PathfinderGoalSelector {
|
||||
private final Map<PathfinderGoal.Type, PathfinderGoalWrapped> c = new EnumMap(PathfinderGoal.Type.class);
|
||||
private final Set<PathfinderGoalWrapped> d = Sets.newLinkedHashSet();private Set<PathfinderGoalWrapped> getTasks() { return d; }// Paper - OBFHELPER
|
||||
private final GameProfilerFiller e;
|
||||
- private final EnumSet<PathfinderGoal.Type> f = EnumSet.noneOf(PathfinderGoal.Type.class);
|
||||
+ private final OptimizedSmallEnumSet<PathfinderGoal.Type> goalTypes = new OptimizedSmallEnumSet<>(PathfinderGoal.Type.class); // Paper - remove streams from pathfindergoalselector
|
||||
private int g = 3;private int getTickRate() { return g; } // Paper - OBFHELPER
|
||||
private int curRate;private int getCurRate() { return curRate; } private void incRate() { this.curRate++; } // Paper TODO
|
||||
|
||||
@@ -0,0 +0,0 @@ public class PathfinderGoalSelector {
|
||||
// Paper end
|
||||
|
||||
public void a(PathfinderGoal pathfindergoal) {
|
||||
- this.d.stream().filter((pathfindergoalwrapped) -> {
|
||||
- return pathfindergoalwrapped.j() == pathfindergoal;
|
||||
- }).filter(PathfinderGoalWrapped::g).forEach(PathfinderGoalWrapped::d);
|
||||
- this.d.removeIf((pathfindergoalwrapped) -> {
|
||||
- return pathfindergoalwrapped.j() == pathfindergoal;
|
||||
- });
|
||||
+ // Paper start - remove streams from pathfindergoalselector
|
||||
+ for (Iterator<PathfinderGoalWrapped> iterator = this.d.iterator(); iterator.hasNext();) {
|
||||
+ PathfinderGoalWrapped goalWrapped = iterator.next();
|
||||
+ if (goalWrapped.j() != pathfindergoal) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (goalWrapped.g()) {
|
||||
+ goalWrapped.d();
|
||||
+ }
|
||||
+ iterator.remove();
|
||||
+ }
|
||||
+ // Paper end - remove streams from pathfindergoalselector
|
||||
}
|
||||
|
||||
+ private static final PathfinderGoal.Type[] PATHFINDER_GOAL_TYPES = PathfinderGoal.Type.values(); // Paper - remove streams from pathfindergoalselector
|
||||
+
|
||||
public void doTick() {
|
||||
this.e.enter("goalCleanup");
|
||||
- this.c().filter((pathfindergoalwrapped) -> {
|
||||
- boolean flag;
|
||||
-
|
||||
- if (pathfindergoalwrapped.g()) {
|
||||
- Stream stream = pathfindergoalwrapped.i().stream();
|
||||
- EnumSet enumset = this.f;
|
||||
-
|
||||
- this.f.getClass();
|
||||
- if (!stream.anyMatch(enumset::contains) && pathfindergoalwrapped.b()) {
|
||||
- flag = false;
|
||||
- return flag;
|
||||
- }
|
||||
+ // Paper start - remove streams from pathfindergoalselector
|
||||
+ for (Iterator<PathfinderGoalWrapped> iterator = this.d.iterator(); iterator.hasNext();) {
|
||||
+ PathfinderGoalWrapped wrappedGoal = iterator.next();
|
||||
+ if (!wrappedGoal.g()) {
|
||||
+ continue;
|
||||
}
|
||||
-
|
||||
- flag = true;
|
||||
- return flag;
|
||||
- }).forEach(PathfinderGoal::d);
|
||||
+ if (!this.goalTypes.hasCommonElements(wrappedGoal.getGoalTypes()) && wrappedGoal.b()) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ wrappedGoal.d();
|
||||
+ }
|
||||
+ // Paper end - remove streams from pathfindergoalselector
|
||||
this.c.forEach((pathfindergoal_type, pathfindergoalwrapped) -> {
|
||||
if (!pathfindergoalwrapped.g()) {
|
||||
this.c.remove(pathfindergoal_type);
|
||||
@@ -0,0 +0,0 @@ public class PathfinderGoalSelector {
|
||||
});
|
||||
this.e.exit();
|
||||
this.e.enter("goalUpdate");
|
||||
- this.d.stream().filter((pathfindergoalwrapped) -> {
|
||||
- return !pathfindergoalwrapped.g();
|
||||
- }).filter((pathfindergoalwrapped) -> {
|
||||
- Stream stream = pathfindergoalwrapped.i().stream();
|
||||
- EnumSet enumset = this.f;
|
||||
-
|
||||
- this.f.getClass();
|
||||
- return stream.noneMatch(enumset::contains);
|
||||
- }).filter((pathfindergoalwrapped) -> {
|
||||
- return pathfindergoalwrapped.i().stream().allMatch((pathfindergoal_type) -> {
|
||||
- return ((PathfinderGoalWrapped) this.c.getOrDefault(pathfindergoal_type, PathfinderGoalSelector.b)).a(pathfindergoalwrapped);
|
||||
- });
|
||||
- }).filter(PathfinderGoalWrapped::a).forEach((pathfindergoalwrapped) -> {
|
||||
- pathfindergoalwrapped.i().forEach((pathfindergoal_type) -> {
|
||||
- PathfinderGoalWrapped pathfindergoalwrapped1 = (PathfinderGoalWrapped) this.c.getOrDefault(pathfindergoal_type, PathfinderGoalSelector.b);
|
||||
-
|
||||
- pathfindergoalwrapped1.d();
|
||||
- this.c.put(pathfindergoal_type, pathfindergoalwrapped);
|
||||
- });
|
||||
- pathfindergoalwrapped.c();
|
||||
- });
|
||||
+ // Paper start - remove streams from pathfindergoalselector
|
||||
+ goal_update_loop: for (Iterator<PathfinderGoalWrapped> iterator = this.d.iterator(); iterator.hasNext();) {
|
||||
+ PathfinderGoalWrapped wrappedGoal = iterator.next();
|
||||
+ if (wrappedGoal.g()) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ OptimizedSmallEnumSet<PathfinderGoal.Type> wrappedGoalSet = wrappedGoal.getGoalTypes();
|
||||
+
|
||||
+ if (this.goalTypes.hasCommonElements(wrappedGoalSet)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ long iterator1 = wrappedGoalSet.getBackingSet();
|
||||
+ int wrappedGoalSize = wrappedGoalSet.size();
|
||||
+ for (int i = 0; i < wrappedGoalSize; ++i) {
|
||||
+ PathfinderGoal.Type type = PATHFINDER_GOAL_TYPES[Long.numberOfTrailingZeros(iterator1)];
|
||||
+ iterator1 ^= com.destroystokyo.paper.util.math.IntegerUtil.getTrailingBit(iterator1);
|
||||
+ PathfinderGoalWrapped wrapped = this.c.getOrDefault(type, PathfinderGoalSelector.b);
|
||||
+ if (!wrapped.a(wrappedGoal)) {
|
||||
+ continue goal_update_loop;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!wrappedGoal.a()) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ iterator1 = wrappedGoalSet.getBackingSet();
|
||||
+ wrappedGoalSize = wrappedGoalSet.size();
|
||||
+ for (int i = 0; i < wrappedGoalSize; ++i) {
|
||||
+ PathfinderGoal.Type type = PATHFINDER_GOAL_TYPES[Long.numberOfTrailingZeros(iterator1)];
|
||||
+ iterator1 ^= com.destroystokyo.paper.util.math.IntegerUtil.getTrailingBit(iterator1);
|
||||
+ PathfinderGoalWrapped wrapped = this.c.getOrDefault(type, PathfinderGoalSelector.b);
|
||||
+
|
||||
+ wrapped.d();
|
||||
+ this.c.put(type, wrappedGoal);
|
||||
+ }
|
||||
+
|
||||
+ wrappedGoal.c();
|
||||
+ }
|
||||
+ // Paper end - remove streams from pathfindergoalselector
|
||||
this.e.exit();
|
||||
this.e.enter("goalTick");
|
||||
- this.c().forEach(PathfinderGoalWrapped::e);
|
||||
+ // Paper start - remove streams from pathfindergoalselector
|
||||
+ for (Iterator<PathfinderGoalWrapped> iterator = this.d.iterator(); iterator.hasNext();) {
|
||||
+ PathfinderGoalWrapped wrappedGoal = iterator.next();
|
||||
+ if (wrappedGoal.g()) {
|
||||
+ wrappedGoal.e();
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - remove streams from pathfindergoalselector
|
||||
this.e.exit();
|
||||
}
|
||||
|
||||
@@ -0,0 +0,0 @@ public class PathfinderGoalSelector {
|
||||
}
|
||||
|
||||
public void a(PathfinderGoal.Type pathfindergoal_type) {
|
||||
- this.f.add(pathfindergoal_type);
|
||||
+ this.goalTypes.addUnchecked(pathfindergoal_type); // Paper - remove streams from pathfindergoalselector
|
||||
}
|
||||
|
||||
public void b(PathfinderGoal.Type pathfindergoal_type) {
|
||||
- this.f.remove(pathfindergoal_type);
|
||||
+ this.goalTypes.removeUnchecked(pathfindergoal_type); // Paper - remove streams from pathfindergoalselector
|
||||
}
|
||||
|
||||
public void a(PathfinderGoal.Type pathfindergoal_type, boolean flag) {
|
||||
diff --git a/src/main/java/net/minecraft/server/PathfinderGoalWrapped.java b/src/main/java/net/minecraft/server/PathfinderGoalWrapped.java
|
||||
index 29657fed75..1b800c558f 100644
|
||||
--- a/src/main/java/net/minecraft/server/PathfinderGoalWrapped.java
|
||||
+++ b/src/main/java/net/minecraft/server/PathfinderGoalWrapped.java
|
||||
@@ -0,0 +0,0 @@ public class PathfinderGoalWrapped extends PathfinderGoal {
|
||||
this.a.a(enumset);
|
||||
}
|
||||
|
||||
- @Override
|
||||
- public EnumSet<PathfinderGoal.Type> i() {
|
||||
- return this.a.i();
|
||||
+ // Paper start - remove streams from pathfindergoalselector
|
||||
+ public com.destroystokyo.paper.util.set.OptimizedSmallEnumSet<PathfinderGoal.Type> getGoalTypes() {
|
||||
+ return this.a.getGoalTypes();
|
||||
+ // Paper end - remove streams from pathfindergoalselector
|
||||
}
|
||||
|
||||
public boolean isRunning() { return this.g(); } // Paper - OBFHELPER
|
||||
--
|
||||
Reference in New Issue
Block a user