Honestly, some of these changes felt like hopium "surely this will fix the lag issues", even tho in my mind these didn't make sense
Yeah, these methods do show up in the profiler, but does these *really* make sense? I don't think so, I think these are just useless patches that only attempt to hide the pain, instead of tackling the REAL issue that is causing these methods to show up in the profiler
Again, this is seems like a small optimization, but it is actually useful because we avoid doing calculations for each block entity, and if your server has a lot of them, it adds up
The "canSee" checks is in a hot path, invoked by each entity for each player on the server if they are in tracking range, so optimizing it is pretty nice
First, we change the original "HashMap" to fastutil's "Object2ObjectOpenHashMap", because the containsKey throughput is better
Then, we add a "isEmpty()" check before attempting to check if the map contains something
This seems stupid, but it does seem that it improves the performance a bit, and it makes sense, "containsKey(...)" does not attempt to check the map size before attempting to check if the map contains the key
We also create a "canSee" method tailored for "ChunkMap#updatePlayer()", a method without the equals check (the "updatePlayer()" already checks if the entity is the same entity) and we cache the "isVisibleByDefault()" result between runs (this also seems a bit overkill because "isVisibleByDefault()" is just a method that returns a boolean, but because this is a hotpath, we need all optimizations that we can get
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.
The "getChunkKey(...)" call is a bit expensive, using 0.24% of CPU time with 19k chunks loaded
So instead of paying the price on each tick, we pay the price when the chunk is loaded
Which, if you think about it, is actually better, since we tick chunks more than we load chunks
Yes, I was shocked, flabbergasted even, when I found out that "Enum.ordinal()" was lagging here
But I guess it makes sense: It is a function that is called every tick for each entity, and it is a bit wasteful converting from enum to ordinal every time
The quintessential patch that other performance forks also have for... some reason
Caches when Bat's spooky season starts and ends, and when Skeleton and Zombies halloween starts and ends
Avoids unnecessary date checks, even tho that this shouldn't really improve performance that much... unless you have a lot of mobs being spawned
On each tick, Paper runs EntityScheduler's executeTick of each entity. This is a bit expensive, due to ArrayDeque's size() call because it ain't a simple "get the current queue size" function, and due to the thread checks.
To avoid the hefty ArrayDeque's size() call, we check if we *really* need to execute the executeTick, by checking if currentlyExecuting is not empty or if oneTimeDelayed is not empty.
Most entities won't have any scheduled tasks, so this is a nice performance bonus. These optimizations, however, wouldn't work in a Folia environment, but because in SparklyPaper executeTick is always executed on the main thread, it ain't an issue for us (yay).
Optimizes "image in map" maps, without requiring the map to be locked, which some old map plugins may not do
This has the disadvantage that the vanilla map data will never be updated while the CraftMapRenderer is not present, but that's not a huuuge problem for us