From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com> Date: Sat, 1 Feb 2025 15:59:29 +0300 Subject: [PATCH] Some optimizations diff --git a/net/minecraft/core/MappedRegistry.java b/net/minecraft/core/MappedRegistry.java index 5f752603aa5611ce9d3dd44cc5b70c27ac46a86e..332122c0b700fb743f91f3fed16aade41dceec28 100644 --- a/net/minecraft/core/MappedRegistry.java +++ b/net/minecraft/core/MappedRegistry.java @@ -34,10 +34,12 @@ public class MappedRegistry implements WritableRegistry { private final ResourceKey> key; private final ObjectList> byId = new ObjectArrayList<>(256); private final Reference2IntMap toId = Util.make(new Reference2IntOpenHashMap<>(2048), map -> map.defaultReturnValue(-1)); // Paper - Perf: Use bigger expected size to reduce collisions - private final Map> byLocation = new HashMap<>(2048); // Paper - Perf: Use bigger expected size to reduce collisions - private final Map, Holder.Reference> byKey = new HashMap<>(2048); // Paper - Perf: Use bigger expected size to reduce collisions - private final Map> byValue = new IdentityHashMap<>(2048); // Paper - Perf: Use bigger expected size to reduce collisions - private final Map, RegistrationInfo> registrationInfos = new IdentityHashMap<>(2048); // Paper - Perf: Use bigger expected size to reduce collisions + // DivineMC start - Some optimizations + private final Map> byLocation = new java.util.concurrent.ConcurrentHashMap<>(2048); // Paper - Perf: Use bigger expected size to reduce collisions + private final Map, Holder.Reference> byKey = new java.util.concurrent.ConcurrentHashMap<>(2048); // Paper - Perf: Use bigger expected size to reduce collisions + private final Map> byValue = Collections.synchronizedMap(new IdentityHashMap<>(2048)); // Paper - Perf: Use bigger expected size to reduce collisions + private final Map, RegistrationInfo> registrationInfos = Collections.synchronizedMap(new IdentityHashMap<>(2048)); // Paper - Perf: Use bigger expected size to reduce collisions + // DivineMC end - Some optimizations private Lifecycle registryLifecycle; private final Map, HolderSet.Named> frozenTags = new IdentityHashMap<>(); MappedRegistry.TagSet allTags = MappedRegistry.TagSet.unbound(); diff --git a/net/minecraft/server/level/ChunkTrackingView.java b/net/minecraft/server/level/ChunkTrackingView.java index bee90335677f7d8b01589ce5cfd81a40fd422886..a5e488d14fd2016ee188b114d0e681562b5b09cc 100644 --- a/net/minecraft/server/level/ChunkTrackingView.java +++ b/net/minecraft/server/level/ChunkTrackingView.java @@ -73,12 +73,12 @@ public interface ChunkTrackingView { } static boolean isWithinDistance(int centerX, int centerZ, int viewDistance, int x, int z, boolean includeOuterChunksAdjacentToViewBorder) { - int i = includeOuterChunksAdjacentToViewBorder ? 2 : 1; - long l = Math.max(0, Math.abs(x - centerX) - i); - long l1 = Math.max(0, Math.abs(z - centerZ) - i); - long l2 = l * l + l1 * l1; - int i1 = viewDistance * viewDistance; - return l2 < i1; + // DivineMC start - Some optimizations + int actualViewDistance = viewDistance + (includeOuterChunksAdjacentToViewBorder ? 1 : 0); + int xDistance = Math.abs(centerX - x); + int zDistance = Math.abs(centerZ - z); + return xDistance <= actualViewDistance && zDistance <= actualViewDistance; + // DivineMC end - Some optimizations } public record Positioned(ChunkPos center, int viewDistance) implements ChunkTrackingView { diff --git a/net/minecraft/util/ClassInstanceMultiMap.java b/net/minecraft/util/ClassInstanceMultiMap.java index 2a708ae0d5bb209650b525e3c56051f8b5655074..762cba15597623f95a242bdd44742d9b892ad042 100644 --- a/net/minecraft/util/ClassInstanceMultiMap.java +++ b/net/minecraft/util/ClassInstanceMultiMap.java @@ -14,9 +14,9 @@ import java.util.Map.Entry; import net.minecraft.Util; public class ClassInstanceMultiMap extends AbstractCollection { - private final Map, List> byClass = Maps.newHashMap(); + private final Map, List> byClass = new it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap<>(); // DivineMC - Some optimizations private final Class baseClass; - private final List allInstances = Lists.newArrayList(); + private final List allInstances = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>(); // DivineMC - Some optimizations public ClassInstanceMultiMap(Class baseClass) { this.baseClass = baseClass; @@ -56,13 +56,27 @@ public class ClassInstanceMultiMap extends AbstractCollection { } public Collection find(Class type) { + // DivineMC start - Some optimizations + List cached = this.byClass.get(type); + if (cached != null) return (Collection) cached; + if (!this.baseClass.isAssignableFrom(type)) { throw new IllegalArgumentException("Don't know how to search for " + type); } else { - List list = this.byClass - .computeIfAbsent(type, clazz -> this.allInstances.stream().filter(clazz::isInstance).collect(Util.toMutableList())); - return (Collection)Collections.unmodifiableCollection(list); + List list = this.byClass.computeIfAbsent(type, + typeClass -> { + it.unimi.dsi.fastutil.objects.ObjectArrayList ts = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>(this.allInstances.size()); + for (Object _allElement : ((it.unimi.dsi.fastutil.objects.ObjectArrayList) this.allInstances).elements()) { + if (typeClass.isInstance(_allElement)) { + ts.add((T) _allElement); + } + } + return ts; + } + ); + return (Collection) list; } + // DivineMC end - Some optimizations } @Override diff --git a/net/minecraft/util/CubicSpline.java b/net/minecraft/util/CubicSpline.java index f36f8f2d49d4eba5c80eb243883749d6f831eb8a..5abd899c88683cb79bb8f02e43c4bfbe8563f496 100644 --- a/net/minecraft/util/CubicSpline.java +++ b/net/minecraft/util/CubicSpline.java @@ -254,31 +254,47 @@ public interface CubicSpline> extends ToFloatFun @Override public float apply(C object) { - float f = this.coordinate.apply(object); - int i = findIntervalStart(this.locations, f); - int i1 = this.locations.length - 1; - if (i < 0) { - return linearExtend(f, this.locations, this.values.get(0).apply(object), this.derivatives, 0); - } else if (i == i1) { - return linearExtend(f, this.locations, this.values.get(i1).apply(object), this.derivatives, i1); + // DivineMC start - Some optimizations + float point = this.coordinate.apply(object); + int rangeForLocation = findIntervalStart(this.locations, point); + int last = this.locations.length - 1; + if (rangeForLocation < 0) { + return linearExtend(point, this.locations, this.values.get(0).apply(object), this.derivatives, 0); + } else if (rangeForLocation == last) { + return linearExtend(point, this.locations, this.values.get(last).apply(object), this.derivatives, last); } else { - float f1 = this.locations[i]; - float f2 = this.locations[i + 1]; - float f3 = (f - f1) / (f2 - f1); - ToFloatFunction toFloatFunction = (ToFloatFunction)this.values.get(i); - ToFloatFunction toFloatFunction1 = (ToFloatFunction)this.values.get(i + 1); - float f4 = this.derivatives[i]; - float f5 = this.derivatives[i + 1]; - float f6 = toFloatFunction.apply(object); - float f7 = toFloatFunction1.apply(object); - float f8 = f4 * (f2 - f1) - (f7 - f6); - float f9 = -f5 * (f2 - f1) + (f7 - f6); - return Mth.lerp(f3, f6, f7) + f3 * (1.0F - f3) * Mth.lerp(f3, f8, f9); + float loc0 = this.locations[rangeForLocation]; + float loc1 = this.locations[rangeForLocation + 1]; + float locDist = loc1 - loc0; + float k = (point - loc0) / locDist; + float n = this.values.get(rangeForLocation).apply(object); + float o = this.values.get(rangeForLocation + 1).apply(object); + float onDist = o - n; + float p = this.derivatives[rangeForLocation] * locDist - onDist; + float q = -this.derivatives[rangeForLocation + 1] * locDist + onDist; + return Mth.lerp(k, n, o) + k * (1.0F - k) * Mth.lerp(k, p, q); } + // DivineMC end - Some optimizations } private static int findIntervalStart(float[] locations, float start) { - return Mth.binarySearch(0, locations.length, i -> start < locations[i]) - 1; + // DivineMC start - Some optimizations + int min = 0; + int i = locations.length; + + while (i > 0) { + int j = i / 2; + int k = min + j; + if (start < locations[k]) { + i = j; + } else { + min = k + 1; + i -= j + 1; + } + } + + return min - 1; + // DivineMC end - Some optimizations } @VisibleForTesting @@ -313,5 +329,27 @@ public interface CubicSpline> extends ToFloatFun this.derivatives ); } + + // DivineMC start - Some optimizations + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Multipoint that = (Multipoint) o; + return java.util.Objects.equals(coordinate, that.coordinate()) && java.util.Arrays.equals(locations, that.locations()) && java.util.Objects.equals(values, that.values()) && java.util.Arrays.equals(derivatives, that.derivatives()); + } + + @Override + public int hashCode() { + int result = 1; + + result = 31 * result + java.util.Objects.hashCode(coordinate); + result = 31 * result + java.util.Arrays.hashCode(locations); + result = 31 * result + java.util.Objects.hashCode(values); + result = 31 * result + java.util.Arrays.hashCode(derivatives); + + return result; + } + // DivineMC end - Some optimizations } } diff --git a/net/minecraft/util/RandomSource.java b/net/minecraft/util/RandomSource.java index 98a54bc4de251014342cda6d0951b7fea79ce553..cd17a4c7f02abf16fcb3b793c10d8b86d47b7974 100644 --- a/net/minecraft/util/RandomSource.java +++ b/net/minecraft/util/RandomSource.java @@ -12,7 +12,7 @@ public interface RandomSource { double GAUSSIAN_SPREAD_FACTOR = 2.297; static RandomSource create() { - return create(RandomSupport.generateUniqueSeed()); + return createThreadSafe(); // DivineMC - Some optimizations } @Deprecated @@ -21,7 +21,7 @@ public interface RandomSource { } static RandomSource create(long seed) { - return new LegacyRandomSource(seed); + return new ThreadSafeLegacyRandomSource(seed); // DivineMC - Some optimizations } static RandomSource createNewThreadLocalInstance() { diff --git a/net/minecraft/util/debugchart/DebugSampleSubscriptionTracker.java b/net/minecraft/util/debugchart/DebugSampleSubscriptionTracker.java index 15de39fa82c7aea18298509fe9587d027c30cc15..c199f99efe25737602a3565ca6f70177571ff886 100644 --- a/net/minecraft/util/debugchart/DebugSampleSubscriptionTracker.java +++ b/net/minecraft/util/debugchart/DebugSampleSubscriptionTracker.java @@ -15,7 +15,7 @@ public class DebugSampleSubscriptionTracker { public static final int STOP_SENDING_AFTER_MS = 10000; private final PlayerList playerList; private final EnumMap> subscriptions; - private final Queue subscriptionRequestQueue = new LinkedList<>(); + private final java.util.List subscriptionRequestQueue = java.util.Collections.synchronizedList(new LinkedList<>()); // DivineMC - Some optimizations public DebugSampleSubscriptionTracker(PlayerList playerList) { this.playerList = playerList; diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java index bc22d67bba9b1ebb6bef84f5326375100d24461d..4aa5ecf3e7a7f58505de583dba7738dc1a596d72 100644 --- a/net/minecraft/world/entity/Mob.java +++ b/net/minecraft/world/entity/Mob.java @@ -841,7 +841,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab if (this.level().getDifficulty() == Difficulty.PEACEFUL && this.shouldDespawnInPeaceful()) { this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause } else if (!this.isPersistenceRequired() && !this.requiresCustomPersistence()) { - Entity nearestPlayer = this.level().findNearbyPlayer(this, -1.0, EntitySelector.PLAYER_AFFECTS_SPAWNING); // Paper - Affects Spawning API + Entity nearestPlayer = this.divinemc$findNearbyPlayer(this.level(), this, -1.0); // Paper - Affects Spawning API // DivineMC - faster player lookup if (nearestPlayer != null) { // Paper start - Configurable despawn distances final io.papermc.paper.configuration.WorldConfiguration.Entities.Spawning.DespawnRangePair despawnRangePair = this.level().paperConfig().entities.spawning.despawnRanges.get(this.getType().getCategory()); @@ -870,6 +870,19 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab } } + // DivineMC start - faster player lookup + private Player divinemc$findNearbyPlayer(Level instance, Entity entity, double maxDistance) { + final Player closestPlayer = instance.getNearestPlayer(entity, this.getType().getCategory().getDespawnDistance()); + if (closestPlayer != null) { + return closestPlayer; + } else { + final List players = this.level().players(); + if (players.isEmpty()) return null; + return players.get(0); + } + } + // DivineMC end - faster player lookup + @Override protected final void serverAiStep() { this.noActionTime++; diff --git a/net/minecraft/world/level/LocalMobCapCalculator.java b/net/minecraft/world/level/LocalMobCapCalculator.java index 9641219c190261dea0db5f95f040a705ba0a3ff9..91966607f8f48b56e2c7e9389bd7d8acda99a48d 100644 --- a/net/minecraft/world/level/LocalMobCapCalculator.java +++ b/net/minecraft/world/level/LocalMobCapCalculator.java @@ -13,16 +13,24 @@ import net.minecraft.world.entity.MobCategory; public class LocalMobCapCalculator { private final Long2ObjectMap> playersNearChunk = new Long2ObjectOpenHashMap<>(); - private final Map playerMobCounts = Maps.newHashMap(); + private final Map playerMobCounts = Maps.newConcurrentMap(); // DivineMC - Some optimizations private final ChunkMap chunkMap; public LocalMobCapCalculator(ChunkMap chunkMap) { this.chunkMap = chunkMap; } - private List getPlayersNear(ChunkPos pos) { - return this.playersNearChunk.computeIfAbsent(pos.toLong(), key -> this.chunkMap.getPlayersCloseForSpawning(pos)); + // DivineMC start - Some optimizations + private synchronized @org.jetbrains.annotations.NotNull List getPlayersNear(ChunkPos pos) { + List retVal = this.playersNearChunk.get(pos.toLong()); + if (retVal == null) { + List newVal = this.chunkMap.getPlayersCloseForSpawning(pos); + this.playersNearChunk.put(pos.toLong(), newVal); + return newVal; + } + return retVal; } + // DivineMC end - Some optimizations public void addMob(ChunkPos pos, MobCategory category) { for (ServerPlayer serverPlayer : this.getPlayersNear(pos)) { @@ -42,14 +50,14 @@ public class LocalMobCapCalculator { } static class MobCounts { - private final Object2IntMap counts = new Object2IntOpenHashMap<>(MobCategory.values().length); + private final int[] spawnGroupDensities = new int[MobCategory.values().length]; // DivineMC - Some optimizations public void add(MobCategory category) { - this.counts.computeInt(category, (key, value) -> value == null ? 1 : value + 1); + this.spawnGroupDensities[category.ordinal()] ++; // DivineMC - Some optimizations } public boolean canSpawn(MobCategory category) { - return this.counts.getOrDefault(category, 0) < category.getMaxInstancesPerChunk(); + return this.spawnGroupDensities[category.ordinal()] < category.getMaxInstancesPerChunk(); // DivineMC - Some optimizations } } } diff --git a/net/minecraft/world/level/storage/DimensionDataStorage.java b/net/minecraft/world/level/storage/DimensionDataStorage.java index d9a3b5a2e6495b7e22c114506c2bd1e406f58f8f..a6e03345afd6d8a38e06a43c59103209618baa14 100644 --- a/net/minecraft/world/level/storage/DimensionDataStorage.java +++ b/net/minecraft/world/level/storage/DimensionDataStorage.java @@ -34,7 +34,7 @@ import org.slf4j.Logger; public class DimensionDataStorage implements AutoCloseable { private static final Logger LOGGER = LogUtils.getLogger(); - public final Map> cache = new HashMap<>(); + public final Map> cache = new java.util.concurrent.ConcurrentHashMap<>(); // DivineMC - Concurrent HashMap private final DataFixer fixerUpper; private final HolderLookup.Provider registries; private final Path dataFolder;