9
0
mirror of https://github.com/LeavesMC/Leaves.git synced 2025-12-21 15:59:33 +00:00
Files
LeavesMC/patches/server/0095-Use-optimized-collection.patch
2023-09-28 18:12:42 +08:00

179 lines
10 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: violetc <58360096+s-yh-china@users.noreply.github.com>
Date: Thu, 20 Jul 2023 16:09:56 +0800
Subject: [PATCH] Use optimized collection
This patch is Powered by Gale(https://github.com/GaleMC/Gale)
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
index 0434bf9b8d3b064c8426d51f9969686a188f0eaa..0ec07834599f1e44784c6cead77c031a3f4251e1 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
@@ -199,7 +199,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
// Paper - rewrite chunk system
this.tickingGenerated = new AtomicInteger();
this.playerMap = new PlayerMap();
- this.entityMap = new Int2ObjectOpenHashMap();
+ this.entityMap = top.leavesmc.leaves.LeavesConfig.useOptimizedCollection ? new it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap() : new Int2ObjectOpenHashMap(); // Leaves - se linked map for entity trackers - provides faster iteration
this.chunkTypeCache = new Long2ByteOpenHashMap();
this.chunkSaveCooldowns = new Long2LongOpenHashMap();
this.unloadQueue = Queues.newConcurrentLinkedQueue();
diff --git a/src/main/java/net/minecraft/util/ClassInstanceMultiMap.java b/src/main/java/net/minecraft/util/ClassInstanceMultiMap.java
index 50a9f33aa31e9273c7c52d4bb2b02f0f884f7ba5..53021c7d173b3c067322e356fead0949aac3fc60 100644
--- a/src/main/java/net/minecraft/util/ClassInstanceMultiMap.java
+++ b/src/main/java/net/minecraft/util/ClassInstanceMultiMap.java
@@ -13,7 +13,7 @@ import java.util.Map;
import java.util.stream.Collectors;
public class ClassInstanceMultiMap<T> extends AbstractCollection<T> {
- private final Map<Class<?>, List<T>> byClass = Maps.newHashMap();
+ private final Map<Class<?>, List<T>> byClass = top.leavesmc.leaves.LeavesConfig.useOptimizedCollection ? new it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap<>(2) : Maps.newHashMap(); // Leaves - replace class map with optimized collection
private final Class<T> baseClass;
private final List<T> allInstances = Lists.newArrayList();
@@ -58,7 +58,7 @@ public class ClassInstanceMultiMap<T> extends AbstractCollection<T> {
if (!this.baseClass.isAssignableFrom(type)) {
throw new IllegalArgumentException("Don't know how to search for " + type);
} else {
- List<? extends T> list = this.byClass.computeIfAbsent(type, (typeClass) -> {
+ List list = this.byClass.computeIfAbsent(type, (typeClass) -> { // Leaves - dev fix
return this.allInstances.stream().filter(typeClass::isInstance).collect(Collectors.toList());
});
return Collections.unmodifiableCollection(list);
diff --git a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java
index 4ee998ae0406d20e3106b7e51911d86313a2e2f8..55640ec8afb2cbb8df6be50d02846d53191e6e32 100644
--- a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java
+++ b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java
@@ -20,8 +20,10 @@ import org.slf4j.Logger;
public class AttributeMap {
private static final Logger LOGGER = LogUtils.getLogger();
- private final Map<Attribute, AttributeInstance> attributes = Maps.newHashMap();
- private final Set<AttributeInstance> dirtyAttributes = Sets.newHashSet();
+ // Leaves start - replace AI attributes with optimized collections
+ private final Map<Attribute, AttributeInstance> attributes = top.leavesmc.leaves.LeavesConfig.useOptimizedCollection ? new it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap<>(0) : Maps.newHashMap();
+ private final Set<AttributeInstance> dirtyAttributes = top.leavesmc.leaves.LeavesConfig.useOptimizedCollection ? new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(0) : Sets.newHashSet();
+ // Leaves end - replace AI attributes with optimized collections
private final AttributeSupplier supplier;
private final java.util.function.Function<Attribute, AttributeInstance> createInstance; // Leaves - reduce entity allocations
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
index b738ee2d3801fadfd09313f05ae24593e56b0ec6..2d1abb9518795875b3719efe91e60508c2c73163 100644
--- a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java
@@ -28,7 +28,7 @@ public class GoalSelector {
}
};
private final Map<Goal.Flag, WrappedGoal> lockedFlags = new EnumMap<>(Goal.Flag.class);
- private final Set<WrappedGoal> availableGoals = Sets.newLinkedHashSet();
+ private final Set<WrappedGoal> availableGoals = top.leavesmc.leaves.LeavesConfig.useOptimizedCollection ? new it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet<>() : Sets.newLinkedHashSet(); // Leaves - replace AI goal set with optimized collection
private final Supplier<ProfilerFiller> profiler;
private final EnumSet<Goal.Flag> disabledFlags = 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 com.destroystokyo.paper.util.set.OptimizedSmallEnumSet<net.minecraft.world.entity.ai.goal.Goal.Flag> goalTypes = new com.destroystokyo.paper.util.set.OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from pathfindergoalselector
diff --git a/src/main/java/net/minecraft/world/level/GameRules.java b/src/main/java/net/minecraft/world/level/GameRules.java
index 6639902efb85b4f49f26ba5f90556fb871ef8a0e..d1c389021503423f20835dac32550da285930392 100644
--- a/src/main/java/net/minecraft/world/level/GameRules.java
+++ b/src/main/java/net/minecraft/world/level/GameRules.java
@@ -137,7 +137,7 @@ public class GameRules {
}
private GameRules(Map<GameRules.Key<?>, GameRules.Value<?>> rules) {
- this.rules = rules;
+ this.rules = top.leavesmc.leaves.LeavesConfig.useOptimizedCollection ? new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(rules) : rules; // Leaves - replace game rules map with optimized collection
// Paper start
int arraySize = rules.keySet().stream().mapToInt(key -> key.gameRuleIndex).max().orElse(-1) + 1;
diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java
index 671a2f0f6f4abe7915644598185092a4ad9106fa..6058750fdc664e674b00551dbbbaeae78c00028a 100644
--- a/src/main/java/net/minecraft/world/level/block/Block.java
+++ b/src/main/java/net/minecraft/world/level/block/Block.java
@@ -61,6 +61,7 @@ import net.minecraft.world.phys.shapes.BooleanOp;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.slf4j.Logger;
+import top.leavesmc.leaves.lithium.common.util.collections.Object2BooleanCacheTable;
public class Block extends BlockBehaviour implements ItemLike {
@@ -72,6 +73,12 @@ public class Block extends BlockBehaviour implements ItemLike {
return !Shapes.joinIsNotEmpty(Shapes.block(), voxelshape, BooleanOp.NOT_SAME);
}
});
+ // Leaves start - replace shape full block cache with hashtable
+ private static final Object2BooleanCacheTable<VoxelShape> LITHIUM_SHAPE_FULL_BLOCK_CACHE = new Object2BooleanCacheTable<>(
+ 1536,
+ shape -> !Shapes.joinIsNotEmpty(Shapes.block(), shape, BooleanOp.NOT_SAME)
+ );
+ // Leaves end - replace shape full block cache with hashtable
public static final int UPDATE_NEIGHBORS = 1;
public static final int UPDATE_CLIENTS = 2;
public static final int UPDATE_INVISIBLE = 4;
diff --git a/src/main/java/top/leavesmc/leaves/lithium/common/util/collections/Object2BooleanCacheTable.java b/src/main/java/top/leavesmc/leaves/lithium/common/util/collections/Object2BooleanCacheTable.java
new file mode 100644
index 0000000000000000000000000000000000000000..45232059b188b5f072e28c4cdf05929005972220
--- /dev/null
+++ b/src/main/java/top/leavesmc/leaves/lithium/common/util/collections/Object2BooleanCacheTable.java
@@ -0,0 +1,62 @@
+package top.leavesmc.leaves.lithium.common.util.collections;
+
+import it.unimi.dsi.fastutil.HashCommon;
+import net.minecraft.util.Mth;
+
+import java.util.function.Predicate;
+
+// Powered by Gale(https://github.com/GaleMC/Gale)
+
+/**
+ * A lossy hashtable implementation that stores a mapping between an object and a boolean.
+ * <p>
+ * Any hash collisions will result in an overwrite: this is safe because the correct value can always be recomputed,
+ * given that the given operator is deterministic.
+ * <p>
+ * This implementation is safe to use from multiple threads
+ */
+public final class Object2BooleanCacheTable<T> {
+
+ private final int mask;
+ private final Node<T>[] nodes;
+ private final Predicate<T> operator;
+
+ @SuppressWarnings("unchecked")
+ public Object2BooleanCacheTable(int capacity, Predicate<T> operator) {
+ int capacity1 = Mth.smallestEncompassingPowerOfTwo(capacity);
+ this.mask = capacity1 - 1;
+ this.nodes = (Node<T>[]) new Node[capacity1];
+ this.operator = operator;
+ }
+
+ private static <T> int hash(T key) {
+ return HashCommon.mix(key.hashCode());
+ }
+
+ public boolean get(T key) {
+ int idx = hash(key) & this.mask;
+
+ Node<T> node = this.nodes[idx];
+ if (node != null && key.equals(node.key)) {
+ return node.value;
+ }
+
+ boolean test = this.operator.test(key);
+ this.nodes[idx] = new Node<>(key, test);
+
+ return test;
+ }
+
+ static class Node<T> {
+
+ final T key;
+ final boolean value;
+
+ Node(T key, boolean value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ }
+
+}