PaperMC/paper-server/patches/features/0007-Optimize-GoalSelector-Goal.Flag-Set-operations.patch

169 lines
8.1 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
2024-12-16 18:07:41 +01:00
index d4f8387254a65b25fc808932a069298d0f8da091..5f5bf0e710ecff09a571091e5a923332be70cb74 100644
2024-12-16 12:25:25 +01:00
--- 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);
2024-12-16 18:07:41 +01:00
+ 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 GoalSelector
+
2024-12-16 18:07:41 +01:00
+ // Paper start - remove streams from GoalSelector; 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);
+ }
+ }
2024-12-16 18:07:41 +01:00
+ // Paper end - remove streams from GoalSelector
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);
2024-12-16 18:07:41 +01:00
+ // Paper start - remove streams from GoalSelector
2021-06-11 14:02:28 +02:00
+ 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 18:07:41 +01:00
+ // Paper end - remove streams from GoalSelector
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;
2024-12-16 18:07:41 +01:00
+ // Paper start - remove streams from GoalSelector
+ public ca.spottedleaf.moonrise.common.set.OptimizedSmallEnumSet<Goal.Flag> getFlags() {
2021-06-11 14:02:28 +02:00
+ return this.goalTypes;
2024-12-16 18:07:41 +01:00
+ // Paper end - remove streams from GoalSelector
2021-06-11 14:02:28 +02:00
}
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
2024-12-16 18:07:41 +01:00
2024-12-16 12:25:25 +01:00
diff --git a/net/minecraft/world/entity/ai/goal/GoalSelector.java b/net/minecraft/world/entity/ai/goal/GoalSelector.java
2024-12-16 18:07:41 +01:00
index eeba224bd575451ba6023df65ef9d9b97f7f1c71..a927c2790c8ab9ccaa7161b970e10b0b44817dd8 100644
2024-12-16 12:25:25 +01:00
--- a/net/minecraft/world/entity/ai/goal/GoalSelector.java
+++ b/net/minecraft/world/entity/ai/goal/GoalSelector.java
2024-12-16 15:17:46 +01:00
@@ -24,7 +24,8 @@ 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-12-16 18:07:41 +01:00
+ private static final Goal.Flag[] GOAL_FLAG_VALUES = Goal.Flag.values(); // Paper - remove streams from GoalSelector
+ 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 GoalSelector
2024-12-16 15:17:46 +01:00
private int curRate; // Paper - EAR 2
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 15:17:46 +01:00
@@ -62,18 +63,18 @@ public class GoalSelector {
2024-12-16 12:25:25 +01:00
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-12-16 15:44:33 +01:00
+ return goal.getFlags().hasCommonElements(flags);
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 15:17:46 +01:00
@@ -87,7 +88,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 15:17:46 +01:00
@@ -97,11 +98,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);
2024-12-16 15:17:46 +01:00
@@ -133,11 +137,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);
2024-12-16 18:07:41 +01:00
+ this.goalTypes.addUnchecked(flag); // Paper - remove streams from GoalSelector
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);
2024-12-16 18:07:41 +01:00
+ this.goalTypes.removeUnchecked(flag); // Paper - remove streams from GoalSelector
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
2024-12-16 18:07:41 +01:00
index 4bdbd323b642ed3422948fe24780be8b503602dc..2c2ab6a1df9d3d23773e44ce4041cc1c21b55163 100644
2024-12-16 12:25:25 +01:00
--- 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 18:07:41 +01:00
+ public ca.spottedleaf.moonrise.common.set.OptimizedSmallEnumSet<Goal.Flag> getFlags() { // Paper - remove streams from GoalSelector
return this.goal.getFlags();
2021-06-11 14:02:28 +02:00
}