PaperMC/feature-patches/1047-Optimize-GoalSelector-Goal.Flag-Set-operations.patch

170 lines
8.3 KiB
Diff
Raw Normal View History

2021-06-11 14:02:28 +02: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-06-11 14:02:28 +02:00
Date: Mon, 6 Apr 2020 17:53:29 -0700
2021-11-24 12:06:34 +01:00
Subject: [PATCH] Optimize GoalSelector Goal.Flag Set operations
2021-06-11 14:02:28 +02:00
2021-11-24 12:06:34 +01:00
Optimise the stream.anyMatch statement to move to a bitset
2021-06-11 14:02:28 +02:00
where we can replace the call with a single bitwise operation.
2024-12-16 12:25:25 +01:00
diff --git a/net/minecraft/world/entity/ai/goal/Goal.java b/net/minecraft/world/entity/ai/goal/Goal.java
index e99836c4073d8b25eddd3b4c784dbdb1f0c4f2b1..a2d788a656b2a5767c8a00bbcaca16efa2db8d24 100644
--- a/net/minecraft/world/entity/ai/goal/Goal.java
+++ b/net/minecraft/world/entity/ai/goal/Goal.java
@@ -7,7 +7,15 @@ import net.minecraft.world.entity.Entity;
2024-10-24 22:29:29 +02:00
import net.minecraft.world.level.Level;
2021-06-11 14:02:28 +02:00
public abstract class Goal {
- private final EnumSet<Goal.Flag> flags = EnumSet.noneOf(Goal.Flag.class);
+ 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
2024-12-16 12:25:25 +01:00
+ protected Goal() {
+ if (this.goalTypes.size() == 0) {
+ this.goalTypes.addUnchecked(Flag.UNKNOWN_BEHAVIOR);
+ }
+ }
+ // Paper end - remove streams from pathfindergoalselector
2021-06-11 14:02:28 +02:00
public abstract boolean canUse();
2021-06-11 14:02:28 +02:00
2024-12-16 12:25:25 +01:00
@@ -33,8 +41,13 @@ public abstract class Goal {
}
2021-06-11 14:02:28 +02:00
2024-12-16 12:25:25 +01:00
public void setFlags(EnumSet<Goal.Flag> flagSet) {
2021-06-11 14:02:28 +02:00
- this.flags.clear();
2024-12-16 12:25:25 +01:00
- this.flags.addAll(flagSet);
2021-06-11 14:02:28 +02:00
+ // Paper start - remove streams from pathfindergoalselector
+ this.goalTypes.clear();
2024-12-16 12:25:25 +01:00
+ this.goalTypes.addAllUnchecked(flagSet);
+ if (this.goalTypes.size() == 0) {
+ this.goalTypes.addUnchecked(Flag.UNKNOWN_BEHAVIOR);
+ }
2024-12-16 12:25:25 +01:00
+ // Paper end - remove streams from pathfindergoalselector;
2021-06-11 14:02:28 +02:00
}
@Override
2024-12-16 12:25:25 +01:00
@@ -42,18 +55,20 @@ public abstract class Goal {
2021-06-11 14:02:28 +02: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-06-11 14:02:28 +02:00
+ return this.goalTypes;
+ // Paper end - remove streams from pathfindergoalselector
}
2024-12-16 12:25:25 +01:00
2024-12-05 11:18:29 +01:00
// Paper start - Mob Goal API
public boolean hasFlag(final Goal.Flag flag) {
- return this.flags.contains(flag);
+ return this.goalTypes.hasElement(flag);
}
public void addFlag(final Goal.Flag flag) {
- this.flags.add(flag);
+ this.goalTypes.addUnchecked(flag);
}
2024-12-16 12:25:25 +01:00
// Paper end - Mob Goal API
diff --git a/net/minecraft/world/entity/ai/goal/GoalSelector.java b/net/minecraft/world/entity/ai/goal/GoalSelector.java
index 9338e63cc28413f5559bb0122ef5e04a84bd51d1..88e7e245824b670652878e03a2142a13e97508fe 100644
--- a/net/minecraft/world/entity/ai/goal/GoalSelector.java
+++ b/net/minecraft/world/entity/ai/goal/GoalSelector.java
@@ -24,7 +24,9 @@ public class GoalSelector {
2024-10-24 22:29:29 +02: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-06-11 14:02:28 +02: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-12-16 12:25:25 +01:00
+
2021-06-11 14:02:28 +02:00
2024-10-24 22:29:29 +02:00
public void addGoal(int priority, Goal goal) {
2024-12-16 12:25:25 +01:00
this.availableGoals.add(new WrappedGoal(priority, goal));
@@ -45,18 +47,18 @@ public class GoalSelector {
this.availableGoals.removeIf(wrappedGoal1 -> wrappedGoal1.getGoal() == goal);
}
2024-04-25 11:42:10 +02:00
2024-12-16 12:25:25 +01:00
- private static boolean goalContainsAnyFlags(WrappedGoal goal, EnumSet<Goal.Flag> flag) {
- for (Goal.Flag flag1 : goal.getFlags()) {
- if (flag.contains(flag1)) {
2023-03-23 22:57:03 +01:00
- return true;
2024-04-25 11:42:10 +02:00
- }
- }
-
2021-11-24 12:06:34 +01:00
- return false;
2024-12-16 12:25:25 +01:00
+ // Paper start - Perf: optimize goal types
+ private static boolean goalContainsAnyFlags(WrappedGoal goal, ca.spottedleaf.moonrise.common.set.OptimizedSmallEnumSet<Goal.Flag> flags) {
2024-04-25 11:42:10 +02:00
+ return goal.getFlags().hasCommonElements(controls);
2021-11-24 12:06:34 +01:00
}
2024-12-16 12:25:25 +01:00
private static boolean goalCanBeReplacedForAllFlags(WrappedGoal goal, Map<Goal.Flag, WrappedGoal> flag) {
- for (Goal.Flag flag1 : 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) {
2024-12-16 12:25:25 +01:00
+ final Goal.Flag flag1 = GOAL_FLAG_VALUES[Long.numberOfTrailingZeros(flagIterator)];
+ flagIterator ^= ca.spottedleaf.concurrentutil.util.IntegerUtil.getTrailingBit(flagIterator);
2024-12-16 12:25:25 +01:00
+ // Paper end - Perf: optimize goal types
if (!flag.getOrDefault(flag1, NO_GOAL).canBeReplacedBy(goal)) {
2021-11-30 09:36:30 +01:00
return false;
2021-11-24 12:06:34 +01:00
}
2024-12-16 12:25:25 +01:00
@@ -70,7 +72,7 @@ public class GoalSelector {
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-12-16 12:25:25 +01:00
@@ -80,11 +82,14 @@ public class GoalSelector {
profilerFiller.push("goalUpdate");
2021-06-11 14:02:28 +02:00
2024-12-16 12:25:25 +01:00
for (WrappedGoal wrappedGoalx : this.availableGoals) {
- if (!wrappedGoalx.isRunning()
- && !goalContainsAnyFlags(wrappedGoalx, this.disabledFlags)
- && goalCanBeReplacedForAllFlags(wrappedGoalx, this.lockedFlags)
- && wrappedGoalx.canUse()) {
- for (Goal.Flag flag : wrappedGoalx.getFlags()) {
2021-11-24 12:06:34 +01:00
+ // Paper start
2024-12-16 12:25:25 +01:00
+ if (!wrappedGoalx.isRunning() && !goalContainsAnyFlags(wrappedGoalx, this.goalTypes) && goalCanBeReplacedForAllFlags(wrappedGoalx, this.lockedFlags) && wrappedGoalx.canUse()) {
+ long flagIterator = wrappedGoalx.getFlags().getBackingSet();
+ int wrappedGoalSize = wrappedGoalx.getFlags().size();
2021-11-30 09:36:30 +01:00
+ 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
2024-12-16 12:25:25 +01:00
WrappedGoal wrappedGoal1 = this.lockedFlags.getOrDefault(flag, NO_GOAL);
wrappedGoal1.stop();
this.lockedFlags.put(flag, wrappedGoalx);
@@ -116,11 +121,11 @@ public class GoalSelector {
2021-06-11 14:02:28 +02:00
}
2024-12-16 12:25:25 +01:00
public void disableControlFlag(Goal.Flag flag) {
- this.disabledFlags.add(flag);
+ this.goalTypes.addUnchecked(flag); // Paper - remove streams from pathfindergoalselector
2021-06-11 14:02:28 +02:00
}
2024-12-16 12:25:25 +01:00
public void enableControlFlag(Goal.Flag flag) {
- this.disabledFlags.remove(flag);
+ this.goalTypes.removeUnchecked(flag); // Paper - remove streams from pathfindergoalselector
2021-06-11 14:02:28 +02:00
}
2024-12-16 12:25:25 +01:00
public void setControlFlag(Goal.Flag flag, boolean enabled) {
diff --git a/net/minecraft/world/entity/ai/goal/WrappedGoal.java b/net/minecraft/world/entity/ai/goal/WrappedGoal.java
index 4bdbd323b642ed3422948fe24780be8b503602dc..5aaad796d2e2f7b57b1fd911a1498cdf235c36be 100644
--- a/net/minecraft/world/entity/ai/goal/WrappedGoal.java
+++ b/net/minecraft/world/entity/ai/goal/WrappedGoal.java
@@ -69,7 +69,7 @@ public class WrappedGoal extends Goal {
2021-06-11 14:02:28 +02:00
}
2021-11-24 12:06:34 +01:00
@Override
2021-06-11 14:02:28 +02:00
- public EnumSet<Goal.Flag> getFlags() {
2024-12-16 12:25:25 +01:00
+ public ca.spottedleaf.moonrise.common.set.OptimizedSmallEnumSet<Goal.Flag> getFlags() { // Paper - remove streams from pathfindergoalselector
return this.goal.getFlags();
2021-06-11 14:02:28 +02:00
}