9
0
mirror of https://github.com/Winds-Studio/Leaf.git synced 2026-01-04 15:41:40 +00:00

use TrackedChunk from ChunkData to prevent hash lookup (#461)

closes #441
This commit is contained in:
hayanesuru
2025-08-15 12:03:29 +09:00
committed by GitHub
parent 91739944e7
commit 8c2b50bdb8
4 changed files with 37 additions and 59 deletions

View File

@@ -28,28 +28,10 @@ However we still recommend to use those packet based NPC plugins,
e.g. ZNPC Plus, Adyeshach, Fancy NPC, etc.
diff --git a/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java b/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java
index 1b8193587814225c2ef2c5d9e667436eb50ff6c5..2a2626e90836ae52a8a686b2040843c6644b6914 100644
index 1b8193587814225c2ef2c5d9e667436eb50ff6c5..356ec20eff799aa12ed6b4f9e54e8721c50a0068 100644
--- a/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java
+++ b/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java
@@ -60,7 +60,16 @@ public final class NearbyPlayers {
private final ServerLevel world;
private final Reference2ReferenceOpenHashMap<ServerPlayer, TrackedPlayer[]> players = new Reference2ReferenceOpenHashMap<>();
- private final Long2ReferenceOpenHashMap<TrackedChunk> byChunk = new Long2ReferenceOpenHashMap<>();
+ // Leaf start - Multithreaded tracker
+ private final it.unimi.dsi.fastutil.longs.Long2ReferenceMap<TrackedChunk> byChunk;
+ {
+ if (org.dreeam.leaf.config.modules.async.MultithreadedTracker.enabled) {
+ byChunk = it.unimi.dsi.fastutil.longs.Long2ReferenceMaps.synchronize(new Long2ReferenceOpenHashMap<>());
+ } else {
+ byChunk = new Long2ReferenceOpenHashMap<>();
+ }
+ }
+ // Leaf end - Multithreaded tracker
private final Long2ReferenceOpenHashMap<ReferenceList<ServerPlayer>>[] directByChunk = new Long2ReferenceOpenHashMap[TOTAL_MAP_TYPES];
{
for (int i = 0; i < this.directByChunk.length; ++i) {
@@ -164,6 +173,8 @@ public final class NearbyPlayers {
@@ -164,6 +164,8 @@ public final class NearbyPlayers {
private int nonEmptyLists;
private long updateCount;
@@ -58,7 +40,7 @@ index 1b8193587814225c2ef2c5d9e667436eb50ff6c5..2a2626e90836ae52a8a686b2040843c6
public TrackedChunk(final long chunkKey, final NearbyPlayers nearbyPlayers) {
this.chunkKey = chunkKey;
this.nearbyPlayers = nearbyPlayers;
@@ -177,6 +188,12 @@ public final class NearbyPlayers {
@@ -177,6 +179,12 @@ public final class NearbyPlayers {
return this.updateCount;
}
@@ -71,7 +53,7 @@ index 1b8193587814225c2ef2c5d9e667436eb50ff6c5..2a2626e90836ae52a8a686b2040843c6
public ReferenceList<ServerPlayer> getPlayers(final NearbyMapType type) {
return this.players[type.ordinal()];
}
@@ -185,6 +202,12 @@ public final class NearbyPlayers {
@@ -185,6 +193,12 @@ public final class NearbyPlayers {
++this.updateCount;
final int idx = type.ordinal();
@@ -84,7 +66,7 @@ index 1b8193587814225c2ef2c5d9e667436eb50ff6c5..2a2626e90836ae52a8a686b2040843c6
final ReferenceList<ServerPlayer> list = this.players[idx];
if (list == null) {
++this.nonEmptyLists;
@@ -203,6 +226,12 @@ public final class NearbyPlayers {
@@ -203,6 +217,12 @@ public final class NearbyPlayers {
++this.updateCount;
final int idx = type.ordinal();
@@ -98,7 +80,7 @@ index 1b8193587814225c2ef2c5d9e667436eb50ff6c5..2a2626e90836ae52a8a686b2040843c6
if (list == null) {
throw new IllegalStateException("Does not contain player " + player);
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java b/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
index bdc1200ef5317fdaf58973bf580b0a672aee800f..e36086cd3c205e66ba1028343028af2239c1d93f 100644
index bdc1200ef5317fdaf58973bf580b0a672aee800f..f34b8012d48ce1b69c1a1529d7ae46b624785ffa 100644
--- a/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
@@ -344,7 +344,7 @@ public final class RegionizedPlayerChunkLoader {
@@ -116,7 +98,7 @@ index bdc1200ef5317fdaf58973bf580b0a672aee800f..e36086cd3c205e66ba1028343028af22
PlayerChunkSender.sendChunk(this.player.connection, this.world, chunk);
+ // Leaf start - Multithreaded tracker
+ if (org.dreeam.leaf.config.modules.async.MultithreadedTracker.enabled) {
+ ca.spottedleaf.moonrise.common.misc.NearbyPlayers.TrackedChunk trackedChunk = this.world.moonrise$getNearbyPlayers().getChunk(chunkX, chunkZ);
+ ca.spottedleaf.moonrise.common.misc.NearbyPlayers.TrackedChunk trackedChunk = chunk.moonrise$getChunkHolder().holderData.nearbyPlayers;
+ if (trackedChunk != null) {
+ trackedChunk.trackingUpdateCountAtomic.getAndIncrement();
+ }

View File

@@ -9,10 +9,10 @@ This patch didn't cahce SectionPos or BlockPos to chunkKey, since they are mutab
The JMH benchmark of this patch can be found in SunBox's `CacheChunkKey`
diff --git a/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java b/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java
index 2a2626e90836ae52a8a686b2040843c6644b6914..283e02b32cae0bc1b0cd71602795aa48987903db 100644
index 356ec20eff799aa12ed6b4f9e54e8721c50a0068..499cad369242f9ad724b3251538d62d8dc8d2ec8 100644
--- a/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java
+++ b/ca/spottedleaf/moonrise/common/misc/NearbyPlayers.java
@@ -136,7 +136,7 @@ public final class NearbyPlayers {
@@ -127,7 +127,7 @@ public final class NearbyPlayers {
}
public TrackedChunk getChunk(final ChunkPos pos) {
@@ -21,7 +21,7 @@ index 2a2626e90836ae52a8a686b2040843c6644b6914..283e02b32cae0bc1b0cd71602795aa48
}
public TrackedChunk getChunk(final BlockPos pos) {
@@ -152,7 +152,7 @@ public final class NearbyPlayers {
@@ -143,7 +143,7 @@ public final class NearbyPlayers {
}
public ReferenceList<ServerPlayer> getPlayers(final ChunkPos pos, final NearbyMapType type) {

View File

@@ -1,6 +1,7 @@
package org.dreeam.leaf.async.tracker;
import ca.spottedleaf.moonrise.common.misc.NearbyPlayers;
import ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity;
import ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity;
import io.papermc.paper.event.player.PlayerTrackEntityEvent;
import io.papermc.paper.event.player.PlayerUntrackEntityEvent;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
@@ -119,31 +120,34 @@ public final class TrackerCtx {
}
void handle(boolean flush) {
handlePackets(world, packets, flush);
if (!pluginEntity.isEmpty()) {
for (final Entity entity : pluginEntity) {
final ChunkMap.TrackedEntity tracker = ((ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity)entity).moonrise$getTrackedEntity();
final ChunkMap.TrackedEntity tracker = ((EntityTrackerEntity) entity).moonrise$getTrackedEntity();
if (tracker == null) {
continue;
}
NearbyPlayers.TrackedChunk trackedChunk = world.moonrise$getNearbyPlayers().getChunk(entity.chunkPosition());
tracker.leafTick(this, trackedChunk);
ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkData chunk = ((ChunkSystemEntity) entity).moonrise$getChunkData();
if (chunk == null) {
continue;
}
tracker.moonrise$tick(chunk.nearbyPlayers);
boolean flag = false;
if (tracker.moonrise$hasPlayers()) {
flag = true;
} else {
FullChunkStatus status = ((ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity) entity).moonrise$getChunkStatus();
FullChunkStatus status = ((ChunkSystemEntity) entity).moonrise$getChunkStatus();
if (status != null && status.isOrAfter(FullChunkStatus.ENTITY_TICKING)) {
flag = true;
}
}
if (flag) {
tracker.serverEntity.leafSendChanges(this, tracker);
tracker.serverEntity.sendChanges();
}
}
pluginEntity.clear();
}
handlePackets(world, packets, flush);
if (!bukkitVelocityEvent.isEmpty()) {
for (ServerPlayer player : bukkitVelocityEvent) {
if (!world.equals(player.level())) {

View File

@@ -1,36 +1,26 @@
package org.dreeam.leaf.async.tracker;
import ca.spottedleaf.moonrise.common.misc.NearbyPlayers;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity;
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkData;
import ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.FullChunkStatus;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.ChunkPos;
import org.dreeam.leaf.util.EntitySlice;
import java.util.concurrent.Callable;
public final class TrackerTask implements Callable<TrackerCtx> {
public final ServerLevel world;
private final EntitySlice entities;
public TrackerTask(ServerLevel world, EntitySlice trackerEntities) {
this.world = world;
this.entities = trackerEntities;
}
public record TrackerTask(ServerLevel world, EntitySlice entities) implements Callable<TrackerCtx> {
@Override
public TrackerCtx call() throws Exception {
NearbyPlayers nearbyPlayers = world.moonrise$getNearbyPlayers();
TrackerCtx ctx = new TrackerCtx(this.world);
final TrackerCtx ctx = new TrackerCtx(this.world);
final Entity[] raw = entities.array();
Long2ObjectMap<NearbyPlayers.TrackedChunk> chunkCache = new Long2ObjectOpenHashMap<>();
for (int i = entities.start(); i < entities.end(); i++) {
final Entity entity = raw[i];
final ChunkMap.TrackedEntity tracker = ((ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity)entity).moonrise$getTrackedEntity();
long chunkPos = entity.chunkPosition().toLong();
final ChunkMap.TrackedEntity tracker = ((EntityTrackerEntity) entity).moonrise$getTrackedEntity();
// removed in world if null
if (tracker == null) {
continue;
}
@@ -38,16 +28,18 @@ public final class TrackerTask implements Callable<TrackerCtx> {
ctx.citizensEntity(entity);
continue;
}
NearbyPlayers.TrackedChunk trackedChunk = chunkCache.computeIfAbsent(chunkPos, k -> nearbyPlayers.getChunk(ChunkPos.getX(k), ChunkPos.getZ(k)));
tracker.leafTick(ctx, trackedChunk);
ChunkData chunkData = ((ChunkSystemEntity) entity).moonrise$getChunkData();
// removed in world if null
if (chunkData == null) {
continue;
}
tracker.leafTick(ctx, chunkData.nearbyPlayers);
boolean flag = false;
if (tracker.moonrise$hasPlayers()) {
flag = true;
} else {
// may read old value
FullChunkStatus status = ((ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity) entity).moonrise$getChunkStatus();
// removed in world
FullChunkStatus status = ((ChunkSystemEntity) entity).moonrise$getChunkStatus();
// removed in world if null
if (status != null && status.isOrAfter(FullChunkStatus.ENTITY_TICKING)) {
flag = true;
}