9
0
mirror of https://github.com/Winds-Studio/Leaf.git synced 2025-12-26 18:39:23 +00:00

Update reduce array allocations

This commit is contained in:
Dreeam
2025-07-25 10:22:55 +08:00
parent 006fe7ce3a
commit ffa437b4aa
4 changed files with 172 additions and 220 deletions

View File

@@ -6,6 +6,18 @@ Subject: [PATCH] Reduce array allocations
License: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
Gale - https://galemc.org
Enum's values returns anew array copy of the enums, this behavior is defined in
`src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java#visitEnumDef`
This is a defensive programming strategy to prevent enums from being modified. However,
copying is unnecessary if we only have read calls.
So we can cache the values result to avoid useless allocations.
Cached as the array since it does not create iterator on the enhanced for loop,
But the list does, and may spend more time than iterating using the array.
The JMH benchmark of this patch can be found in SunBox's `CachedEnumValuesForLoop`
This patch is based on the following patch:
"reduce allocs"
By: Simon Gardling <titaniumtown@gmail.com>
@@ -250,7 +262,7 @@ index 0e44397c9d53ff30a96c9e8e392a363fa9ae0c55..dbf31389f0e9796c80afbffddf6a20cb
private final EquipmentSlot.Type type;
private final int index;
diff --git a/net/minecraft/world/entity/EquipmentSlotGroup.java b/net/minecraft/world/entity/EquipmentSlotGroup.java
index 381e0a1c0af7e339713ed1df1c2f21121c1bbd0f..1ebcab2ee9898a618ad76b18491be19859629192 100644
index 381e0a1c0af7e339713ed1df1c2f21121c1bbd0f..4e847c3f9d761da5dda11dec60582d9d9e630b37 100644
--- a/net/minecraft/world/entity/EquipmentSlotGroup.java
+++ b/net/minecraft/world/entity/EquipmentSlotGroup.java
@@ -24,6 +24,7 @@ public enum EquipmentSlotGroup implements StringRepresentable, Iterable<Equipmen
@@ -261,15 +273,6 @@ index 381e0a1c0af7e339713ed1df1c2f21121c1bbd0f..1ebcab2ee9898a618ad76b18491be198
public static final IntFunction<EquipmentSlotGroup> BY_ID = ByIdMap.continuous(
equipmentSlotGroup -> equipmentSlotGroup.id, values(), ByIdMap.OutOfBoundsStrategy.ZERO
);
@@ -38,7 +39,7 @@ public enum EquipmentSlotGroup implements StringRepresentable, Iterable<Equipmen
this.id = id;
this.key = key;
this.predicate = predicate;
- this.slots = EquipmentSlot.VALUES.stream().filter(predicate).toList();
+ this.slots = EquipmentSlot.VALUES.stream().filter(predicate).toList(); // Gale - JettPack - reduce array allocations
}
private EquipmentSlotGroup(final int id, final String key, final EquipmentSlot slot) {
diff --git a/net/minecraft/world/entity/EquipmentTable.java b/net/minecraft/world/entity/EquipmentTable.java
index b383836c200ca9f7bd84639367aa81b57868fb25..3af4a6dcc81afaf2860325fe5852c9a941f216d4 100644
--- a/net/minecraft/world/entity/EquipmentTable.java
@@ -283,6 +286,112 @@ index b383836c200ca9f7bd84639367aa81b57868fb25..3af4a6dcc81afaf2860325fe5852c9a9
}
private static Map<EquipmentSlot, Float> createForAllSlots(List<EquipmentSlot> equipmentSlots, float dropChance) {
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index 395ebf0a5fa14d9ff43b2d2e8e63aeaaf4612443..c6f87ee9b7c2b0bfc2d459a86b60ad2eaa23b594 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -3358,7 +3358,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
Map<org.bukkit.inventory.EquipmentSlot, io.papermc.paper.event.entity.EntityEquipmentChangedEvent.EquipmentChange> equipmentChanges = null;
// Paper end - EntityEquipmentChangedEvent
- for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES) {
+ for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES_ARRAY) { // Gale - JettPack - reduce array allocations
ItemStack itemStack = this.lastEquipmentItems.get(equipmentSlot);
ItemStack itemBySlot = this.getItemBySlot(equipmentSlot);
if (this.equipmentHasChanged(itemStack, itemBySlot)) {
@@ -3630,7 +3630,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
public boolean canGlide() {
if (!this.onGround() && !this.isPassenger() && !this.hasEffect(MobEffects.LEVITATION)) {
- for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES) {
+ for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES_ARRAY) { // Gale - JettPack - reduce array allocations
if (canGlideUsing(this.getItemBySlot(equipmentSlot), equipmentSlot)) {
return true;
}
diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java
index 4d4b58b684ca115f4d8f672362d4c8252ef9481a..939d8c53a8eb445c1b5b0c65842ecb64ad317252 100644
--- a/net/minecraft/world/entity/Mob.java
+++ b/net/minecraft/world/entity/Mob.java
@@ -338,7 +338,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
if (this.xpReward > 0) {
int i = this.xpReward;
- for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES) {
+ for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES_ARRAY) { // Gale - JettPack - reduce array allocations
if (equipmentSlot.canIncreaseExperience()) {
ItemStack itemBySlot = this.getItemBySlot(equipmentSlot);
if (!itemBySlot.isEmpty() && this.dropChances.byEquipment(equipmentSlot) <= 1.0F) {
@@ -950,7 +950,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
protected void dropCustomDeathLoot(ServerLevel level, DamageSource damageSource, boolean recentlyHit) {
super.dropCustomDeathLoot(level, damageSource, recentlyHit);
- for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES) {
+ for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES_ARRAY) { // Gale - JettPack - reduce array allocations
if (this.shouldSkipLoot(equipmentSlot)) continue; // Paper
ItemStack itemBySlot = this.getItemBySlot(equipmentSlot);
float f = this.dropChances.byEquipment(equipmentSlot);
@@ -994,7 +994,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
public Set<EquipmentSlot> dropPreservedEquipment(ServerLevel level, Predicate<ItemStack> filter) {
Set<EquipmentSlot> set = new HashSet<>();
- for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES) {
+ for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES_ARRAY) { // Gale - JettPack - reduce array allocations
ItemStack itemBySlot = this.getItemBySlot(equipmentSlot);
if (!itemBySlot.isEmpty()) {
if (!filter.test(itemBySlot)) {
@@ -1122,7 +1122,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
protected void populateDefaultEquipmentEnchantments(ServerLevelAccessor level, RandomSource random, DifficultyInstance difficulty) {
this.enchantSpawnedWeapon(level, random, difficulty);
- for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES) {
+ for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES_ARRAY) { // Gale - JettPack - reduce array allocations
if (equipmentSlot.getType() == EquipmentSlot.Type.HUMANOID_ARMOR) {
this.enchantSpawnedArmor(level, random, equipmentSlot, difficulty);
}
@@ -1539,7 +1539,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
protected void removeAfterChangingDimensions() {
super.removeAfterChangingDimensions();
- for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES) {
+ for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES_ARRAY) { // Gale - JettPack - reduce array allocations
ItemStack itemBySlot = this.getItemBySlot(equipmentSlot);
if (!itemBySlot.isEmpty()) {
itemBySlot.setCount(0);
diff --git a/net/minecraft/world/entity/decoration/ArmorStand.java b/net/minecraft/world/entity/decoration/ArmorStand.java
index 5ee368580d878a3845349c3d50cc0dc549c42cab..9952e84dd94b8773c5ba8fcc4526e7714ebc2136 100644
--- a/net/minecraft/world/entity/decoration/ArmorStand.java
+++ b/net/minecraft/world/entity/decoration/ArmorStand.java
@@ -456,7 +456,7 @@ public class ArmorStand extends LivingEntity {
this.playBrokenSound();
// this.dropAllDeathLoot(level, damageSource); // CraftBukkit - moved down
- for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES) {
+ for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES_ARRAY) { // Gale - JettPack - reduce array allocations
ItemStack itemStack = this.equipment.get(equipmentSlot); // Paper - move equipment removal past event call
if (!itemStack.isEmpty()) {
this.drops.add(new DefaultDrop(itemStack, stack -> Block.popResource(this.level(), this.blockPosition().above(), stack))); // CraftBukkit - add to drops // Paper - Restore vanilla drops behavior; mirror so we can destroy it later - though this call site was safe & spawn drops correctly}
@@ -465,7 +465,7 @@ public class ArmorStand extends LivingEntity {
// Paper start - move equipment removal past event call
org.bukkit.event.entity.EntityDeathEvent event = this.dropAllDeathLoot(level, damageSource);
if (!event.isCancelled()) {
- for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES) {
+ for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES_ARRAY) { // Gale - JettPack - reduce array allocations
this.equipment.set(equipmentSlot, ItemStack.EMPTY);
}
}
diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java
index e5e08dbefead90e9fe2bb05e4f0257f7aa4c0686..5160c349f1ace36d6de11f23e0f957f37fc19165 100644
--- a/net/minecraft/world/entity/player/Player.java
+++ b/net/minecraft/world/entity/player/Player.java
@@ -413,7 +413,7 @@ public abstract class Player extends LivingEntity {
}
private boolean isEquipped(Item item) {
- for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES) {
+ for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES_ARRAY) { // Gale - JettPack - reduce array allocations
ItemStack itemBySlot = this.getItemBySlot(equipmentSlot);
Equippable equippable = itemBySlot.get(DataComponents.EQUIPPABLE);
if (itemBySlot.is(item) && equippable != null && equippable.slot() == equipmentSlot) {
diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java
index da16f4831c875e07c25d7ed041bed493db614658..951c86278e8cb5cd801a5db2ebfabef8c6d813ef 100644
--- a/net/minecraft/world/item/ItemStack.java
@@ -309,6 +418,41 @@ index bfda76974ea8d4397e2c2ebf5bdcb5d7e5f0bab5..cabbc93409ca99180d115e2f23419ee1
} else {
String[] strings = new String[pattern.size() - i3 - i2];
diff --git a/net/minecraft/world/item/enchantment/Enchantment.java b/net/minecraft/world/item/enchantment/Enchantment.java
index 7a620eb92b1e672cedd72ec4d986c01eba337686..0460da0124d2c48b7fed45fa182537fd8059135d 100644
--- a/net/minecraft/world/item/enchantment/Enchantment.java
+++ b/net/minecraft/world/item/enchantment/Enchantment.java
@@ -109,7 +109,7 @@ public record Enchantment(Component description, Enchantment.EnchantmentDefiniti
public Map<EquipmentSlot, ItemStack> getSlotItems(LivingEntity entity) {
Map<EquipmentSlot, ItemStack> map = Maps.newEnumMap(EquipmentSlot.class);
- for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES) {
+ for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES_ARRAY) { // Gale - JettPack - reduce array allocations
if (this.matchingSlot(equipmentSlot)) {
ItemStack itemBySlot = entity.getItemBySlot(equipmentSlot);
if (!itemBySlot.isEmpty()) {
diff --git a/net/minecraft/world/item/enchantment/EnchantmentHelper.java b/net/minecraft/world/item/enchantment/EnchantmentHelper.java
index 66234431b265e0596275ca468cd40f8da98c22e2..b20415b47e209aedbc60ff17238e575dfe33849a 100644
--- a/net/minecraft/world/item/enchantment/EnchantmentHelper.java
+++ b/net/minecraft/world/item/enchantment/EnchantmentHelper.java
@@ -153,7 +153,7 @@ public class EnchantmentHelper {
}
private static void runIterationOnEquipment(LivingEntity entity, EnchantmentHelper.EnchantmentInSlotVisitor visitor) {
- for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES) {
+ for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES_ARRAY) { // Gale - JettPack - reduce array allocations
runIterationOnItem(entity.getItemBySlot(equipmentSlot), equipmentSlot, entity, visitor);
}
}
@@ -467,7 +467,7 @@ public class EnchantmentHelper {
public static Optional<EnchantedItemInUse> getRandomItemWith(DataComponentType<?> componentType, LivingEntity entity, Predicate<ItemStack> filter) {
List<EnchantedItemInUse> list = new ArrayList<>();
- for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES) {
+ for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES_ARRAY) { // Gale - JettPack - reduce array allocations
ItemStack itemBySlot = entity.getItemBySlot(equipmentSlot);
if (filter.test(itemBySlot)) {
ItemEnchantments itemEnchantments = itemBySlot.getOrDefault(DataComponents.ENCHANTMENTS, ItemEnchantments.EMPTY);
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
index a0254e85fccebb66ce02bd58f9d461addd8ad73d..1f7b3db02e59c4cbc93bc0e4e42bd20e0031c4bd 100644
--- a/net/minecraft/world/level/Level.java

View File

@@ -9,7 +9,7 @@ Gale - https://galemc.org
The JMH benchmark of this patch can be found in SunBox's `RecordHashCode`
diff --git a/ca/spottedleaf/moonrise/patches/collisions/util/FluidOcclusionCacheKey.java b/ca/spottedleaf/moonrise/patches/collisions/util/FluidOcclusionCacheKey.java
index cf9ffdeff6bf0b62a45f7a44dbfe0dd7d17dc4f4..f1480625eaece1553d4a96ec54138a463a6fc1ca 100644
index cf9ffdeff6bf0b62a45f7a44dbfe0dd7d17dc4f4..fcff01c84d611a75dbf79b1644092516c7cfb0bc 100644
--- a/ca/spottedleaf/moonrise/patches/collisions/util/FluidOcclusionCacheKey.java
+++ b/ca/spottedleaf/moonrise/patches/collisions/util/FluidOcclusionCacheKey.java
@@ -3,5 +3,58 @@ package ca.spottedleaf.moonrise.patches.collisions.util;
@@ -17,7 +17,7 @@ index cf9ffdeff6bf0b62a45f7a44dbfe0dd7d17dc4f4..f1480625eaece1553d4a96ec54138a46
import net.minecraft.world.level.block.state.BlockState;
-public record FluidOcclusionCacheKey(BlockState first, BlockState second, Direction direction, boolean result) {
+// Gale start - Lithium - cache FluidOcclusionCacheKey hash
+// Gale start - cache FluidOcclusionCacheKey hash
+public final class FluidOcclusionCacheKey {
+ private final BlockState first;
+ private final BlockState second;
@@ -70,5 +70,5 @@ index cf9ffdeff6bf0b62a45f7a44dbfe0dd7d17dc4f4..f1480625eaece1553d4a96ec54138a46
+ "direction=" + direction + ", " +
+ "result=" + result + ']';
+ }
+ // Gale end - Lithium - cache FluidOcclusionCacheKey hash
+ // Gale end - cache FluidOcclusionCacheKey hash
}

View File

@@ -6,6 +6,18 @@ Subject: [PATCH] Reduce array allocations
License: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
Gale - https://galemc.org
Enum's values returns anew array copy of the enums, this behavior is defined in
`src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java#visitEnumDef`
This is a defensive programming strategy to prevent enums from being modified. However,
copying is unnecessary if we only have read calls.
So we can cache the values result to avoid useless allocations.
Cached as the array since it does not create iterator on the enhanced for loop,
But the list does, and may spend more time than iterating using the array.
The JMH benchmark of this patch can be found in SunBox's `CachedEnumValuesForLoop`
This patch is based on the following patch:
"reduce allocs"
By: Simon Gardling <titaniumtown@gmail.com>
@@ -98,7 +110,7 @@ index db92261a6cb3758391108361096417c61bc82cdc..1a14fddb36ca3c14d243304db629d0c5
public SortedList(final E[] elements, final Comparator<? super E> comparator) {
diff --git a/src/main/java/io/papermc/paper/command/brigadier/PaperCommands.java b/src/main/java/io/papermc/paper/command/brigadier/PaperCommands.java
index af480008adc07c63344d625101d1bf42fab96b5d..8c9609b95cf27b6316c48a554b2c508aa527b964 100644
index f37adc5dcad50a3e313c63ebee795161b4fa8b8f..948460266c6fd40b7b5197f81aa5ed90dc54b66a 100644
--- a/src/main/java/io/papermc/paper/command/brigadier/PaperCommands.java
+++ b/src/main/java/io/papermc/paper/command/brigadier/PaperCommands.java
@@ -178,7 +178,7 @@ public class PaperCommands implements Commands, PaperRegistrar<LifecycleEventOwn
@@ -124,7 +136,7 @@ index 58ca24715eafd1ac3cc9657b1cc235049d69bb59..acb764b71bb3e8f159a758002f7d1077
return true;
}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java
index 4abe58077fae4e68cceda9624fed013bca1d6f22..72aa906ccf64dd9be085728a897f323ab0822eba 100644
index 4abe58077fae4e68cceda9624fed013bca1d6f22..dbbff2c73ae995f847b470a1e0853583cc377dc4 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java
@@ -165,7 +165,7 @@ public class CraftEntityEquipment implements EntityEquipment {
@@ -132,7 +144,7 @@ index 4abe58077fae4e68cceda9624fed013bca1d6f22..72aa906ccf64dd9be085728a897f323a
@Override
public void clear() {
- for (net.minecraft.world.entity.EquipmentSlot slot : net.minecraft.world.entity.EquipmentSlot.values()) {
+ for (net.minecraft.world.entity.EquipmentSlot slot : net.minecraft.world.entity.EquipmentSlot.VALUES) { // Gale - JettPack - reduce array allocations
+ for (net.minecraft.world.entity.EquipmentSlot slot : net.minecraft.world.entity.EquipmentSlot.VALUES_ARRAY) { // Gale - JettPack - reduce array allocations
this.setEquipment(slot, null, false);
}
}