diff --git a/README.md b/README.md index 548e65e..b88f531 100644 --- a/README.md +++ b/README.md @@ -27,10 +27,8 @@ SparklyPaper's config file is `sparklypaper.yml`, the file is, by default, place * But still, if you made your own custom "image on map" plugin, don't forget to `mapView.isLocked = true` to get the same performance benefits in vanilla Paper! * Fix concurrency issues when using `imageToBytes` in multiple threads * Useful if one of your plugins is parallelizng map creation on server startup -* Optimize `ServerStatsCounter`'s dirty set - * Instead of using Java's HashSet, we will use fastutil's `ObjectOpenHashSet`, which has better performance - * While this seems stupid, awardStat was using around ~0.14% when adding to the `HashSet`, and that's not good - * We also optimized the `getDirty` calls. I mean, the *only* `getDirty` call. Because the map was only retrieved once, we don't actually need to create a copy of the map just to iterate it, we can just access it directly and clear it manually after use. +* Skip dirty stats copy when requesting player stats + * There's literally only one `getDirty` call. Because the map was only retrieved once, we don't actually need to create a copy of the map just to iterate it, we can just access it directly and clear it manually after use. * ~~Avoid unnecessary `ItemFrame#getItem()` calls~~ * ~~When ticking an item frame, on each tick, it checks if the item on the item frame is a map and, if it is, it adds the map to be carried by the entity player~~ * ~~However, the `getItem()` call is a bit expensive, especially because this is only really used if the item in the item frame is a map~~ diff --git a/patches/server/0009-Optimize-ServerStatsCounter-s-dirty-set.patch b/patches/server/0009-Optimize-ServerStatsCounter-s-dirty-set.patch deleted file mode 100644 index acd84c1..0000000 --- a/patches/server/0009-Optimize-ServerStatsCounter-s-dirty-set.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MrPowerGamerBR -Date: Sat, 18 Nov 2023 20:35:44 -0300 -Subject: [PATCH] Optimize ServerStatsCounter's dirty set - -Instead of using Java's HashSet, we will use fastutil's ObjectOpenHashSet, which has better performance - -While this seems stupid, awardStat was using around ~0.14% when adding to the HashSet, and that's not good - -We also optimized the getDirty calls, since the map was only retrieved once, so in that case, we don't actually need to create a copy of the map just to iterate it - -diff --git a/src/main/java/net/minecraft/stats/ServerStatsCounter.java b/src/main/java/net/minecraft/stats/ServerStatsCounter.java -index 9bb8d4d7be6a937980aa653db82be084d066a563..142b42e906cd1c10c17bd82bfb19cf4d252fbd34 100644 ---- a/src/main/java/net/minecraft/stats/ServerStatsCounter.java -+++ b/src/main/java/net/minecraft/stats/ServerStatsCounter.java -@@ -43,7 +43,7 @@ public class ServerStatsCounter extends StatsCounter { - private static final Logger LOGGER = LogUtils.getLogger(); - private final MinecraftServer server; - private final File file; -- private final Set> dirty = Sets.newHashSet(); -+ private final Set> dirty = new it.unimi.dsi.fastutil.objects.ObjectOpenHashSet(); // SparklyPaper - optimize ServerStatsCounter's dirty set - - public ServerStatsCounter(MinecraftServer server, File file) { - this.server = server; -@@ -85,12 +85,15 @@ public class ServerStatsCounter extends StatsCounter { - this.dirty.add(stat); - } - -+ // SparklyPaper - Optimize ServerStatsCounter's dirty set -+ /* - private Set> getDirty() { - Set> set = Sets.newHashSet(this.dirty); - - this.dirty.clear(); - return set; - } -+ */ - - public void parseLocal(DataFixer dataFixer, String json) { - try { -@@ -238,13 +241,14 @@ public class ServerStatsCounter extends StatsCounter { - - public void sendStats(ServerPlayer player) { - Object2IntMap> object2intmap = new Object2IntOpenHashMap(); -- Iterator iterator = this.getDirty().iterator(); -+ Iterator iterator = this.dirty.iterator(); // SparklyPaper - Optimize ServerStatsCounter's dirty set - - while (iterator.hasNext()) { - Stat statistic = (Stat) iterator.next(); - - object2intmap.put(statistic, this.getValue(statistic)); - } -+ this.dirty.clear(); // SparklyPaper - Optimize ServerStatsCounter's dirty set - - player.connection.send(new ClientboundAwardStatsPacket(object2intmap)); - } diff --git a/patches/server/0009-Skip-dirty-stats-copy-when-requesting-player-stats.patch b/patches/server/0009-Skip-dirty-stats-copy-when-requesting-player-stats.patch new file mode 100644 index 0000000..d9a7589 --- /dev/null +++ b/patches/server/0009-Skip-dirty-stats-copy-when-requesting-player-stats.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MrPowerGamerBR +Date: Wed, 22 Nov 2023 14:40:36 -0300 +Subject: [PATCH] Skip dirty stats copy when requesting player stats + +There's literally only one getDirty call. Because the map was only retrieved once, we don't actually need to create a copy of the map just to iterate it, we can just access it directly and clear it manually after use. + +diff --git a/src/main/java/net/minecraft/stats/ServerStatsCounter.java b/src/main/java/net/minecraft/stats/ServerStatsCounter.java +index 9bb8d4d7be6a937980aa653db82be084d066a563..e93722fd8b7a97037914beddbace9a0de5dca8b4 100644 +--- a/src/main/java/net/minecraft/stats/ServerStatsCounter.java ++++ b/src/main/java/net/minecraft/stats/ServerStatsCounter.java +@@ -85,12 +85,16 @@ public class ServerStatsCounter extends StatsCounter { + this.dirty.add(stat); + } + ++ // SparklyPaper start - Skip dirty stats copy when requesting player stats ++ /* + private Set> getDirty() { + Set> set = Sets.newHashSet(this.dirty); + + this.dirty.clear(); + return set; + } ++ */ ++ // SparklyPaper end + + public void parseLocal(DataFixer dataFixer, String json) { + try { +@@ -238,7 +242,7 @@ public class ServerStatsCounter extends StatsCounter { + + public void sendStats(ServerPlayer player) { + Object2IntMap> object2intmap = new Object2IntOpenHashMap(); +- Iterator iterator = this.getDirty().iterator(); ++ Iterator iterator = this.dirty.iterator(); // SparklyPaper - Skip dirty stats copy when requesting player stats + + while (iterator.hasNext()) { + Stat statistic = (Stat) iterator.next(); +@@ -246,6 +250,8 @@ public class ServerStatsCounter extends StatsCounter { + object2intmap.put(statistic, this.getValue(statistic)); + } + ++ this.dirty.clear(); // SparklyPaper - Skip dirty stats copy when requesting player stats ++ + player.connection.send(new ClientboundAwardStatsPacket(object2intmap)); + } + }