From ad71c13e4b2d14fe2a88375977fd8f0386f183ff Mon Sep 17 00:00:00 2001 From: MrHua269 Date: Sun, 28 Jan 2024 09:54:29 +0000 Subject: [PATCH] Added some new optimizations --- ...Sparkly-Paper-Optimize-canSee-checks.patch | 50 +++++ ...Skip-entity-move-if-movement-is-zero.patch | 42 ++++ ...ck-frozen-ticks-before-landing-block.patch | 31 +++ ...er-lootable-refresh-for-non-player-i.patch | 19 ++ ...058-Gale-Use-platform-math-functions.patch | 187 ++++++++++++++++++ ...aster-floating-point-positive-modulo.patch | 54 +++++ 6 files changed, 383 insertions(+) create mode 100644 patches/server/0054-Sparkly-Paper-Optimize-canSee-checks.patch create mode 100644 patches/server/0055-Gale-Skip-entity-move-if-movement-is-zero.patch create mode 100644 patches/server/0056-Gale-Check-frozen-ticks-before-landing-block.patch create mode 100644 patches/server/0057-Gale-Don-t-trigger-lootable-refresh-for-non-player-i.patch create mode 100644 patches/server/0058-Gale-Use-platform-math-functions.patch create mode 100644 patches/server/0059-Gale-Faster-floating-point-positive-modulo.patch diff --git a/patches/server/0054-Sparkly-Paper-Optimize-canSee-checks.patch b/patches/server/0054-Sparkly-Paper-Optimize-canSee-checks.patch new file mode 100644 index 0000000..23fb47e --- /dev/null +++ b/patches/server/0054-Sparkly-Paper-Optimize-canSee-checks.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MrHua269 +Date: Sun, 28 Jan 2024 09:51:56 +0000 +Subject: [PATCH] Sparkly Paper Optimize canSee checks + + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 4709782f3e858edfa6ce25696462eb45909885ee..3cba356b74362c2fc010d0c1bfb6eeecb449908e 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -1419,7 +1419,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Folia end - region threading + + // CraftBukkit start - respect vanish API +- if (flag && (!io.papermc.paper.util.TickThread.isTickThreadFor(player) || !player.getBukkitEntity().canSee(this.entity.getBukkitEntity()))) { // Paper - only consider hits // Folia - region threading ++ if (flag && (!io.papermc.paper.util.TickThread.isTickThreadFor(player) || !player.getBukkitEntity().canSeeChunkMapUpdatePlayer(this.entity.getBukkitEntity()))) { // Paper - only consider hits // Folia - region threading // SparklyPaper - optimize canSee checks + flag = false; + } + // CraftBukkit end +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 06c92a2d3ecb3b747c2303819f72c1c41967af8c..7ae6925732c347ec97c94c5fdfd0012fbe6820fc 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -183,7 +183,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + private boolean hasPlayedBefore = false; + private final ConversationTracker conversationTracker = new ConversationTracker(); + private final Set channels = new HashSet(); +- private final Map>> invertedVisibilityEntities = new HashMap<>(); ++ private final Map>> invertedVisibilityEntities = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(); // SparklyPaper - optimize canSee checks + private final Set unlistedEntities = new HashSet<>(); // Paper + private static final WeakHashMap> pluginWeakReferences = new WeakHashMap<>(); + private int hash = 0; +@@ -2075,9 +2075,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + + @Override + public boolean canSee(org.bukkit.entity.Entity entity) { +- return this.equals(entity) || entity.isVisibleByDefault() ^ this.invertedVisibilityEntities.containsKey(entity.getUniqueId()); // SPIGOT-7312: Can always see self ++ return this.equals(entity) || entity.isVisibleByDefault() ^ (!invertedVisibilityEntities.isEmpty() && this.invertedVisibilityEntities.containsKey(entity.getUniqueId())); // SPIGOT-7312: Can always see self // SparklyPaper - optimize canSee checks + } + ++ // SparklyPaper - optimize canSee checks ++ // The check in ChunkMap#updatePlayer already rejects if it is the same entity, so we don't need to check it twice, especially because CraftPlayer's equals check is a bit expensive ++ public boolean canSeeChunkMapUpdatePlayer(org.bukkit.entity.Entity entity) { ++ return entity.isVisibleByDefault() ^ (!invertedVisibilityEntities.isEmpty() && this.invertedVisibilityEntities.containsKey(entity.getUniqueId())); // SPIGOT-7312: Can always see self // SparklyPaper - optimize canSee checks ++ } ++ // SparklyPaper end ++ + public boolean canSee(UUID uuid) { + org.bukkit.entity.Entity entity = this.getServer().getPlayer(uuid); + if (entity == null) { diff --git a/patches/server/0055-Gale-Skip-entity-move-if-movement-is-zero.patch b/patches/server/0055-Gale-Skip-entity-move-if-movement-is-zero.patch new file mode 100644 index 0000000..ff8c449 --- /dev/null +++ b/patches/server/0055-Gale-Skip-entity-move-if-movement-is-zero.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MrHua269 +Date: Sun, 28 Jan 2024 09:52:09 +0000 +Subject: [PATCH] Gale Skip entity move if movement is zero + + +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 18fdb265714584d4ee759d86cc8a10b13742e153..ec255db477e6308cc0fbe336b7bebeac75b97b2a 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -317,6 +317,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { + public float yRotO; + public float xRotO; + private AABB bb; ++ private boolean boundingBoxChanged = false; // Gale - VMP - skip entity move if movement is zero + public boolean onGround; + public boolean horizontalCollision; + public boolean verticalCollision; +@@ -1090,6 +1091,11 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { + //Luminol end + + public void move(MoverType movementType, Vec3 movement) { ++ // Gale start - VMP - skip entity move if movement is zero ++ if (!this.boundingBoxChanged && movement.equals(Vec3.ZERO)) { ++ return; ++ } ++ // Gale end - VMP - skip entity move if movement is zero + // Paper start - detailed watchdog information + io.papermc.paper.util.TickThread.ensureTickThread("Cannot move an entity off-main"); + //Luminol start - Fix high position moving +@@ -4875,6 +4881,11 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { + } + + public final void setBoundingBox(AABB boundingBox) { ++ // Gale start - VMP - skip entity move if movement is zero ++ if (!this.bb.equals(boundingBox)) { ++ this.boundingBoxChanged = true; ++ } ++ // Gale end - VMP - skip entity move if movement is zero + // CraftBukkit start - block invalid bounding boxes + double minX = boundingBox.minX, + minY = boundingBox.minY, diff --git a/patches/server/0056-Gale-Check-frozen-ticks-before-landing-block.patch b/patches/server/0056-Gale-Check-frozen-ticks-before-landing-block.patch new file mode 100644 index 0000000..a4e8b80 --- /dev/null +++ b/patches/server/0056-Gale-Check-frozen-ticks-before-landing-block.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MrHua269 +Date: Sun, 28 Jan 2024 09:52:24 +0000 +Subject: [PATCH] Gale Check frozen ticks before landing block + + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index ecbacbed29af51d949122b21c3ae9fc95885c6d8..3c83ff19c40eb44eae3ed9f7db4f5291d080b32c 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -591,11 +591,10 @@ public abstract class LivingEntity extends Entity implements Attackable { + } + + protected void tryAddFrost() { +- if (!this.getBlockStateOnLegacy().isAir()) { + int i = this.getTicksFrozen(); + + if (i > 0) { +- AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ AttributeInstance attributemodifiable = this.getBlockStateOnLegacy().isAir() ? null : this.getAttribute(Attributes.MOVEMENT_SPEED); // Gale - Lithium - check frozen ticks before landing block + + if (attributemodifiable == null) { + return; +@@ -605,7 +604,6 @@ public abstract class LivingEntity extends Entity implements Attackable { + + attributemodifiable.addTransientModifier(new AttributeModifier(LivingEntity.SPEED_MODIFIER_POWDER_SNOW_UUID, "Powder snow slow", (double) f, AttributeModifier.Operation.ADDITION)); + } +- } + + } + diff --git a/patches/server/0057-Gale-Don-t-trigger-lootable-refresh-for-non-player-i.patch b/patches/server/0057-Gale-Don-t-trigger-lootable-refresh-for-non-player-i.patch new file mode 100644 index 0000000..25e1095 --- /dev/null +++ b/patches/server/0057-Gale-Don-t-trigger-lootable-refresh-for-non-player-i.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MrHua269 +Date: Sun, 28 Jan 2024 09:52:48 +0000 +Subject: [PATCH] Gale Don't trigger lootable refresh for non-player + interaction + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java +index 02364a148b347e3669275553004391e31d77c0b5..6c6ed0e9877c7e0c9804f3c2c786a61c301e318f 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java +@@ -70,6 +70,7 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc + } + + public void unpackLootTable(@Nullable Player player) { ++ if (player == null) return; // Gale - EMC - don't trigger lootable refresh for non-player interaction + if (this.level != null && this.lootableData.shouldReplenish(player) && this.level.getServer() != null) { // Paper - don't unpack loot table if not in world + LootTable lootTable = this.level.getServer().getLootData().getLootTable(this.lootTable); + if (player instanceof ServerPlayer) { diff --git a/patches/server/0058-Gale-Use-platform-math-functions.patch b/patches/server/0058-Gale-Use-platform-math-functions.patch new file mode 100644 index 0000000..7cb4584 --- /dev/null +++ b/patches/server/0058-Gale-Use-platform-math-functions.patch @@ -0,0 +1,187 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MrHua269 +Date: Sun, 28 Jan 2024 09:31:27 +0000 +Subject: [PATCH] Gale Use platform math functions + +License: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html) +Gale - https://galemc.org + +This patch is based on the following patch: +"Use Math.floor instead of fastfloor" +By: Xymb +As part of: Kaiiju (https://github.com/KaiijuMC/Kaiiju) +Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html) + +* Comparison of floor methods used in Paper * + +Measure shown is floored number of milliseconds +(nanoseconds integer-divided by 1_000_000 +taken to get the floor of 1000 randomly chosen doubles +(all in the range of [-Integer.MAX_VALUE + 10, Integer.MAX_VALUE - 10]) +100_000 times (making it 100_000_000 floor operations total) +and adding it to a total. + +We are testing the following methods: +* net.minecraft.util.Mth.floor +* java.lang.Math.floor +* java.lang.StrictMath.floor +* org.apache.commons.math3.util.FastMath.floor +* org.apache.commons.math3.util.FastMath.floor, but with a hot start (see comment in code) +* io.papermc.paper.util.MCUtil.fastFloor + +The tests performed clearly show that Math.floor is the fastest. +This is most likely due to java.lang.Math's usage of the @IntrinsicCandidate +annotation, which allows the JVM to use a more optimized implementation at runtime. +However, in the case that there is no intrinsic replacement for Math.floor, +it defers to StrictMath.floor, which relies on a number of native methods, and is +still much faster than the existing Minecraft utility functions. +Therefore, using Math.floor instead of these functions is better regardless. +In Apache Commons Math 4, FastMath.floor has also been removed in favor of Math.floor. + +The versions used: +* Windows 10 Home 21H2 19044.3086 +* OpenJDK Runtime Environment Temurin-19.0.2+7 (build 19.0.2+7) +* Paper a3c760e6af1e8c7244ef75c6da6e6df278a79e14 on Minecraft 1.20.1 +* Apache Commons Math 3.6.1 + +Results: +Total is of type int Total is of type double +---------------------------------------------------------------------------------- +Mth.floor 2113 (double) Mth.floor 2658 +(int) Math.floor 130 Math.floor 194 +(int) StrictMath.floor 835 StrictMath.floor 381 +(int) FastMath.floor 412 FastMath.floor 376 +(int) FastMath.floor with hot start 359 FastMath.floor with hot start 321 +MCUtil.fastFloor 2284 (double) MCUtil.fastFloor 2469 + +Code is below: +```java +package somepackage; + +import io.papermc.paper.util.MCUtil; +import net.minecraft.util.Mth; + +import java.util.Random; + +public class Main { + + public static void main(String[] args) { + + // IF FastMath.floor with a hot start: + // FastMath.floor(37485.5); + + var random = new Random(4889338); + int size = 1000; + var values = new double[size]; + double bound = Integer.MAX_VALUE - 10; + for (int i = 0; i < size; i++) { + values[i] = random.nextDouble(bound * 2) - bound; + } + int repeats = 100_000; + + // int total = 0; + // OR + // double total = 0; + + long start = System.nanoTime(); + for (int repeat = 0; repeat < repeats; repeat++) { + for (int index = 0; index < size; index++) { + total += insert_function_being_tested_here(values[index]); + } + } + long diff = System.nanoTime() - start; + System.out.println(total); + System.out.println(diff / 1_000_000L); + + } + +} +``` + +diff --git a/src/main/java/io/papermc/paper/util/MCUtil.java b/src/main/java/io/papermc/paper/util/MCUtil.java +index a149d98be7b4744f18d4ed4940881e13a76e4a7c..ad61afcfe1d0b01b17bc02977e8ff2b8d0420088 100644 +--- a/src/main/java/io/papermc/paper/util/MCUtil.java ++++ b/src/main/java/io/papermc/paper/util/MCUtil.java +@@ -166,13 +166,11 @@ public final class MCUtil { + } + + public static int fastFloor(double x) { +- int truncated = (int)x; +- return x < (double)truncated ? truncated - 1 : truncated; ++ return (int) Math.floor(x); // Gale - use platform math functions + } + + public static int fastFloor(float x) { +- int truncated = (int)x; +- return x < (double)truncated ? truncated - 1 : truncated; ++ return (int) Math.floor(x); // Gale - use platform math functions + } + + public static float normalizeYaw(float f) { +@@ -233,11 +231,11 @@ public final class MCUtil { + } + + public static int getChunkCoordinate(final double coordinate) { +- return MCUtil.fastFloor(coordinate) >> 4; ++ return ((int) Math.floor(coordinate)) >> 4; // Gale - use platform math functions + } + + public static int getBlockCoordinate(final double coordinate) { +- return MCUtil.fastFloor(coordinate); ++ return (int) Math.floor(coordinate); // Gale - use platform math functions + } + + public static long getBlockKey(final int x, final int y, final int z) { +diff --git a/src/main/java/net/minecraft/util/Mth.java b/src/main/java/net/minecraft/util/Mth.java +index 33ace08d15bbcad66c09c7bd65dd03e784246e8f..d04586223a9b2a30efb17da01fb7f3e8f2a6af7b 100644 +--- a/src/main/java/net/minecraft/util/Mth.java ++++ b/src/main/java/net/minecraft/util/Mth.java +@@ -51,13 +51,11 @@ public class Mth { + } + + public static int floor(float value) { +- int i = (int)value; +- return value < (float)i ? i - 1 : i; ++ return (int) Math.floor(value); // Gale - use platform math functions + } + + public static int floor(double value) { +- int i = (int)value; +- return value < (double)i ? i - 1 : i; ++ return (int) Math.floor(value); // Gale - use platform math functions + } + + public static long lfloor(double value) { +@@ -74,13 +72,11 @@ public class Mth { + } + + public static int ceil(float value) { +- int i = (int)value; +- return value > (float)i ? i + 1 : i; ++ return (int) Math.ceil(value); // Gale - use platform math functions + } + + public static int ceil(double value) { +- int i = (int)value; +- return value > (double)i ? i + 1 : i; ++ return (int) Math.ceil(value); // Gale - use platform math functions + } + + public static int clamp(int value, int min, int max) { +@@ -116,15 +112,7 @@ public class Mth { + } + + public static double absMax(double a, double b) { +- if (a < 0.0D) { +- a = -a; +- } +- +- if (b < 0.0D) { +- b = -b; +- } +- +- return Math.max(a, b); ++ return Math.max(Math.abs(a), Math.abs(b)); // Gale - use platform math functions + } + + public static int floorDiv(int dividend, int divisor) { diff --git a/patches/server/0059-Gale-Faster-floating-point-positive-modulo.patch b/patches/server/0059-Gale-Faster-floating-point-positive-modulo.patch new file mode 100644 index 0000000..8a020d6 --- /dev/null +++ b/patches/server/0059-Gale-Faster-floating-point-positive-modulo.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MrHua269 +Date: Sun, 28 Jan 2024 09:31:27 +0000 +Subject: [PATCH] Gale Faster floating-point positive modulo + +License: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html) +Gale - https://galemc.org + +diff --git a/src/main/java/net/minecraft/util/Mth.java b/src/main/java/net/minecraft/util/Mth.java +index d04586223a9b2a30efb17da01fb7f3e8f2a6af7b..bae83b708cafb867f43d5378fa78818fc382e2fa 100644 +--- a/src/main/java/net/minecraft/util/Mth.java ++++ b/src/main/java/net/minecraft/util/Mth.java +@@ -143,14 +143,26 @@ public class Mth { + return Math.floorMod(dividend, divisor); + } + +- public static float positiveModulo(float dividend, float divisor) { ++ public static float positiveModuloForAnyDivisor(float dividend, float divisor) { // Gale - faster floating-point positive modulo + return (dividend % divisor + divisor) % divisor; + } + +- public static double positiveModulo(double dividend, double divisor) { ++ public static double positiveModuloForAnyDivisor(double dividend, double divisor) { // Gale - faster floating-point positive modulo + return (dividend % divisor + divisor) % divisor; + } + ++ // Gale start - faster floating-point positive modulo ++ public static float positiveModuloForPositiveIntegerDivisor(float dividend, float divisor) { ++ var modulo = dividend % divisor; ++ return modulo < 0 ? modulo + divisor : modulo; ++ } ++ ++ public static double positiveModuloForPositiveIntegerDivisor(double dividend, double divisor) { ++ var modulo = dividend % divisor; ++ return modulo < 0 ? modulo + divisor : modulo; ++ } ++ // Gale end - faster floating-point positive modulo ++ + public static boolean isMultipleOf(int a, int b) { + return a % b == 0; + } +diff --git a/src/main/java/net/minecraft/world/level/levelgen/blending/Blender.java b/src/main/java/net/minecraft/world/level/levelgen/blending/Blender.java +index 8d40205f56a7b204a65505f9e1b4e20000221755..fe4a27e9e8265fc60e1db6dd070f91b212904e30 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/blending/Blender.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/blending/Blender.java +@@ -139,7 +139,7 @@ public class Blender { + private static double heightToOffset(double height) { + double d = 1.0D; + double e = height + 0.5D; +- double f = Mth.positiveModulo(e, 8.0D); ++ double f = Mth.positiveModuloForPositiveIntegerDivisor(e, 8.0D); // Gale - faster floating-point positive modulo + return 1.0D * (32.0D * (e - 128.0D) - 3.0D * (e - 120.0D) * f + 3.0D * f * f) / (128.0D * (32.0D - 3.0D * f)); + } +