Repository navigation
Conversation
|
And with this change, what is the percentage improvement compared to the previous implementation? Also it will be good to provide how you logged those values, such as spark report links |
|
And doing the math, 4 seconds out of 25 minutes of CPU time (30k ticks) is averaging out to 4s / 30000 ticks = 0.133 ms/tick. So it's seems to be only taking 0.27% of each server tick on average which is not much of an issue. |
|
Fair point, the CPU cost is small – your 0.27 %/tick math matches what I see. The motivation was mostly that it’s one of the hottest events on our server (~6.9k PreCreatureSpawnEvent/s) and every call allocated Option/lambda objects. In our alloc profiles Multiverse-Core is ~0.35 % of all allocations. So it’s a small cleanup of GC churn on a hot path, not a big win. I’ll post before/after spark links Before: I'll share new ones soon |
|
The entire reason of using optional api is to remove these types of null checks. 0.27 %/tick for like so many spawn events shows that its not a performance issue at all. |
Problem
PreCreatureSpawnEventandCreatureSpawnEventfire thousands of times per second on busy servers. Every call allocated several short-lived objects even when no world restricts spawning:WorldManager#getLoadedWorld(World): threeOptioninstances and two lambdasOption#peekwith a lambda capturing the eventSpawnCategoryMapper#getSpawnCategory: anOptionplus themaplambdaEntitySpawnConfig#getSpawnCategoryConfig:computeIfAbsentwith a capturing lambdaOn a production Paper server with about 6,900
PreCreatureSpawnEvent/s, a spark profile showedMVEntityListener$1.onEventat about 4 s of CPU per 25 minutes and over 6 MB/s of allocations. All worlds on that server allow every spawn, so all of this was overhead.Changes
WorldManager#getLoadedWorldOrNull(World)(@ApiStatus.Internal) andWorldStore#getLoadedWorldOrNull(String). The existingOptionmethods now delegate to them.SpawnCategoryMapper#getSpawnCategoryOrNull(EntityType), used byEntitySpawnConfig#shouldAllowSpawn.EntitySpawnConfig#getSpawnCategoryConfigdoes a plaingetbefore falling back tocomputeIfAbsent.MVEntityListenerspawn handlers share one small helper that uses the null-returning lookups.The spawn decision is unchanged: worlds not managed by Multiverse and entity types without a known spawn category still always allow spawning, and restricted worlds cancel exactly as before. No config or public API behaviour changes.
Testing
./gradlew buildpasses, all 183 existing tests green (same as before the change).