Paper/patches/server/0981-Optimize-GoalSelector-Goal.Flag-Set-operations.patch

163 lines
8.5 KiB
Diff
Raw Permalink Normal View History

2021-11-24 12:06:34 +01:00
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
Rewrite chunk system (#8177) Patch documentation to come Issues with the old system that are fixed now: - World generation does not scale with cpu cores effectively. - Relies on the main thread for scheduling and maintaining chunk state, dropping chunk load/generate rates at lower tps. - Unreliable prioritisation of chunk gen/load calls that block the main thread. - Shutdown logic is utterly unreliable, as it has to wait for all chunks to unload - is it guaranteed that the chunk system is in a state on shutdown that it can reliably do this? Watchdog shutdown also typically failed due to thread checks, which is now resolved. - Saving of data is not unified (i.e can save chunk data without saving entity data, poses problems for desync if shutdown is really abnormal. - Entities are not loaded with chunks. This caused quite a bit of headache for Chunk#getEntities API, but now the new chunk system loads entities with chunks so that they are ready whenever the chunk loads in. Effectively brings the behavior back to 1.16 era, but still storing entities in their own separate regionfiles. The above list is not complete. The patch documentation will complete it. New chunk system hard relies on starlight and dataconverter, and most importantly the new concurrent utilities in ConcurrentUtil. Some of the old async chunk i/o interface (i.e the old file io thread reroutes _some_ calls to the new file io thread) is kept for plugin compat reasons. It will be removed in the next major version of minecraft. The old legacy chunk system patches have been moved to the removed folder in case we need them again.
2022-09-26 10:02:51 +02:00
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
2021-11-24 12:06:34 +01:00
Date: Mon, 6 Apr 2020 17:53:29 -0700
Subject: [PATCH] Optimize GoalSelector Goal.Flag Set operations
Optimise the stream.anyMatch statement to move to a bitset
where we can replace the call with a single bitwise operation.
Feature patch
2021-11-24 12:06:34 +01:00
diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java
2024-10-24 22:29:29 +02:00
index acc25b08ed3b9f978229fa017d23f9fa0da519e3..71c952621580fe95730835ed0eab7c9852550030 100644
2021-11-24 12:06:34 +01:00
--- a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java
2024-10-24 22:29:29 +02:00
@@ -7,7 +7,16 @@ import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.Level;
2021-11-24 12:06:34 +01:00
public abstract class Goal {
- private final EnumSet<Goal.Flag> flags = EnumSet.noneOf(Goal.Flag.class);
+ private final EnumSet<Goal.Flag> flags = EnumSet.noneOf(Goal.Flag.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be.
+ private final ca.spottedleaf.moonrise.common.set.OptimizedSmallEnumSet<net.minecraft.world.entity.ai.goal.Goal.Flag> goalTypes = new ca.spottedleaf.moonrise.common.set.OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from pathfindergoalselector
+
+ // Paper start - remove streams from pathfindergoalselector; make sure types are not empty
+ public Goal() {
+ if (this.goalTypes.size() == 0) {
+ this.goalTypes.addUnchecked(Flag.UNKNOWN_BEHAVIOR);
+ }
+ }
+ // Paper end - remove streams from pathfindergoalselector
2021-11-24 12:06:34 +01:00
public abstract boolean canUse();
2024-10-24 22:29:29 +02:00
@@ -33,8 +42,13 @@ public abstract class Goal {
2021-11-24 12:06:34 +01:00
}
public void setFlags(EnumSet<Goal.Flag> controls) {
- this.flags.clear();
- this.flags.addAll(controls);
+ // Paper start - remove streams from pathfindergoalselector
+ this.goalTypes.clear();
+ this.goalTypes.addAllUnchecked(controls);
+ if (this.goalTypes.size() == 0) {
+ this.goalTypes.addUnchecked(Flag.UNKNOWN_BEHAVIOR);
+ }
2021-11-24 12:06:34 +01:00
+ // Paper end - remove streams from pathfindergoalselector
}
@Override
2024-10-24 22:29:29 +02:00
@@ -42,8 +56,10 @@ public abstract class Goal {
2021-11-24 12:06:34 +01:00
return this.getClass().getSimpleName();
}
- public EnumSet<Goal.Flag> getFlags() {
- return this.flags;
+ // Paper start - remove streams from pathfindergoalselector
+ public ca.spottedleaf.moonrise.common.set.OptimizedSmallEnumSet<Goal.Flag> getFlags() {
2021-11-24 12:06:34 +01:00
+ return this.goalTypes;
+ // Paper end - remove streams from pathfindergoalselector
}
protected int adjustedTickDelay(int ticks) {
diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java
2024-10-24 22:29:29 +02:00
index d871975f943a04b49644dc6eb18314d65a7836dc..29ae74339a4831ccef3d01e8054931715ba192ad 100644
2021-11-24 12:06:34 +01:00
--- a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java
2024-10-24 22:29:29 +02:00
@@ -24,7 +24,8 @@ public class GoalSelector {
};
2021-11-24 12:06:34 +01:00
private final Map<Goal.Flag, WrappedGoal> lockedFlags = new EnumMap<>(Goal.Flag.class);
2024-04-25 11:42:10 +02:00
private final Set<WrappedGoal> availableGoals = new ObjectLinkedOpenHashSet<>();
2021-11-24 12:06:34 +01:00
- private final EnumSet<Goal.Flag> disabledFlags = EnumSet.noneOf(Goal.Flag.class);
2024-04-25 11:42:10 +02:00
+ private static final Goal.Flag[] GOAL_FLAG_VALUES = Goal.Flag.values(); // Paper - remove streams from pathfindergoalselector
+ private final ca.spottedleaf.moonrise.common.set.OptimizedSmallEnumSet<net.minecraft.world.entity.ai.goal.Goal.Flag> goalTypes = new ca.spottedleaf.moonrise.common.set.OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from pathfindergoalselector
2024-10-24 22:29:29 +02:00
private int curRate; // Paper - EAR 2
2021-11-24 12:06:34 +01:00
2024-10-24 22:29:29 +02:00
public void addGoal(int priority, Goal goal) {
@@ -60,18 +61,18 @@ public class GoalSelector {
2024-04-25 11:42:10 +02:00
this.availableGoals.removeIf(wrappedGoalx -> wrappedGoalx.getGoal() == goal);
2021-11-24 12:06:34 +01:00
}
2024-04-25 11:42:10 +02:00
2023-03-23 22:57:03 +01:00
- private static boolean goalContainsAnyFlags(WrappedGoal goal, EnumSet<Goal.Flag> controls) {
- for (Goal.Flag flag : goal.getFlags()) {
2023-03-23 22:57:03 +01:00
- if (controls.contains(flag)) {
- return true;
2024-04-25 11:42:10 +02:00
- }
- }
-
2021-11-24 12:06:34 +01:00
- return false;
2024-04-25 11:42:10 +02:00
+ // Paper start
+ private static boolean goalContainsAnyFlags(WrappedGoal goal, ca.spottedleaf.moonrise.common.set.OptimizedSmallEnumSet<Goal.Flag> controls) {
2024-04-25 11:42:10 +02:00
+ return goal.getFlags().hasCommonElements(controls);
2021-11-24 12:06:34 +01:00
}
private static boolean goalCanBeReplacedForAllFlags(WrappedGoal goal, Map<Goal.Flag, WrappedGoal> goalsByControl) {
- for (Goal.Flag flag : goal.getFlags()) {
2021-11-30 09:36:30 +01:00
+ long flagIterator = goal.getFlags().getBackingSet();
+ int wrappedGoalSize = goal.getFlags().size();
+ for (int i = 0; i < wrappedGoalSize; ++i) {
+ final Goal.Flag flag = GOAL_FLAG_VALUES[Long.numberOfTrailingZeros(flagIterator)];
+ flagIterator ^= ca.spottedleaf.concurrentutil.util.IntegerUtil.getTrailingBit(flagIterator);
2021-11-30 09:36:30 +01:00
+ // Paper end
2021-11-24 12:06:34 +01:00
if (!goalsByControl.getOrDefault(flag, NO_GOAL).canBeReplacedBy(goal)) {
2021-11-30 09:36:30 +01:00
return false;
2021-11-24 12:06:34 +01:00
}
2024-10-24 22:29:29 +02:00
@@ -85,7 +86,7 @@ public class GoalSelector {
2021-11-24 12:06:34 +01:00
profilerFiller.push("goalCleanup");
for (WrappedGoal wrappedGoal : this.availableGoals) {
2021-11-24 12:06:34 +01:00
- if (wrappedGoal.isRunning() && (goalContainsAnyFlags(wrappedGoal, this.disabledFlags) || !wrappedGoal.canContinueToUse())) {
+ if (wrappedGoal.isRunning() && (goalContainsAnyFlags(wrappedGoal, this.goalTypes) || !wrappedGoal.canContinueToUse())) { // Paper - Perf: optimize goal types by removing streams
2021-11-24 12:06:34 +01:00
wrappedGoal.stop();
}
}
2024-10-24 22:29:29 +02:00
@@ -95,11 +96,14 @@ public class GoalSelector {
2021-11-24 12:06:34 +01:00
profilerFiller.push("goalUpdate");
for (WrappedGoal wrappedGoal2 : this.availableGoals) {
- if (!wrappedGoal2.isRunning()
- && !goalContainsAnyFlags(wrappedGoal2, this.disabledFlags)
- && goalCanBeReplacedForAllFlags(wrappedGoal2, this.lockedFlags)
- && wrappedGoal2.canUse()) {
- for (Goal.Flag flag : wrappedGoal2.getFlags()) {
2021-11-24 12:06:34 +01:00
+ // Paper start
+ if (!wrappedGoal2.isRunning() && !goalContainsAnyFlags(wrappedGoal2, this.goalTypes) && goalCanBeReplacedForAllFlags(wrappedGoal2, this.lockedFlags) && wrappedGoal2.canUse()) {
2021-11-30 09:36:30 +01:00
+ long flagIterator = wrappedGoal2.getFlags().getBackingSet();
+ int wrappedGoalSize = wrappedGoal2.getFlags().size();
+ for (int i = 0; i < wrappedGoalSize; ++i) {
+ final Goal.Flag flag = GOAL_FLAG_VALUES[Long.numberOfTrailingZeros(flagIterator)];
+ flagIterator ^= ca.spottedleaf.concurrentutil.util.IntegerUtil.getTrailingBit(flagIterator);
2021-11-24 12:06:34 +01:00
+ // Paper end
WrappedGoal wrappedGoal3 = this.lockedFlags.getOrDefault(flag, NO_GOAL);
wrappedGoal3.stop();
this.lockedFlags.put(flag, wrappedGoal2);
2024-10-24 22:29:29 +02:00
@@ -131,11 +135,11 @@ public class GoalSelector {
2021-11-24 12:06:34 +01:00
}
public void disableControlFlag(Goal.Flag control) {
- this.disabledFlags.add(control);
+ this.goalTypes.addUnchecked(control); // Paper - remove streams from pathfindergoalselector
2021-11-24 12:06:34 +01:00
}
public void enableControlFlag(Goal.Flag control) {
- this.disabledFlags.remove(control);
+ this.goalTypes.removeUnchecked(control); // Paper - remove streams from pathfindergoalselector
2021-11-24 12:06:34 +01:00
}
public void setControlFlag(Goal.Flag control, boolean enabled) {
diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java
index b02d3deb550830245c8945ef17d3073ea930fdda..8cf2e0db6b2f7d3a50f2ac1c3f4f0c6c2434b5ba 100644
2021-11-24 12:06:34 +01:00
--- a/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java
@@ -69,8 +69,10 @@ public class WrappedGoal extends Goal {
}
@Override
- public EnumSet<Goal.Flag> getFlags() {
+ // Paper start - remove streams from pathfindergoalselector
+ public ca.spottedleaf.moonrise.common.set.OptimizedSmallEnumSet<Goal.Flag> getFlags() {
2021-11-24 12:06:34 +01:00
return this.goal.getFlags();
+ // Paper end - remove streams from pathfindergoalselector
}
public boolean isRunning() {