初步多线程支持
Some checks failed
check-does-build / build (push) Failing after 7s

This commit is contained in:
2026-01-06 15:38:06 +08:00
parent fa751fd473
commit 49e92b4190
4 changed files with 70 additions and 5 deletions

View File

@@ -33,6 +33,17 @@ public class DirtyUpdateService {
section.acquire();
this.dirtyQueue.add(new DirtySection(world, section, updateFlags, neighborMsk));
// Logger.info("Section dirty: " + section.lvl + " " + section.x + " " + section.y + " " + section.z);
int lvl = section.lvl;
int sx = section.x;
int sz = section.z;
int m = (1 << (lvl + 1)) - 1;
for (int dx = 0; dx <= m; dx++) {
for (int dz = 0; dz <= m; dz++) {
int absX = (sx << (lvl + 1)) | dx;
int absZ = (sz << (lvl + 1)) | dz;
this.instance.getVisibleBandCache().invalidate(absX, absZ);
}
}
}
}
@@ -121,7 +132,8 @@ public class DirtyUpdateService {
int absZ = (int) it[1];
int minAbsY = (sy << (lvl + 1));
int maxAbsY = minAbsY + m;
int[] yList = VisibleBandUtil.computeVisibleBands(matchLevel, dirty.world, absX, absZ);
int[] yList = this.instance.getVisibleBandCache().getOrSchedule(matchLevel, dirty.world, absX, absZ);
if (yList == null) continue;
for (int i = 0; i < yList.length && perPlayerBudget > 0; i++) {
int absY = yList[i];
if (absY < minAbsY || absY > maxAbsY) continue;

View File

@@ -109,8 +109,11 @@ public class PlayerLodTracker {
long key = (((long)x) << 32) ^ (z & 0xffffffffL);
var prog = state.sentColumns.computeIfAbsent(key, k -> new ColumnProgress());
if (prog.yList == null) {
prog.yList = VisibleBandUtil.computeVisibleBands(level, engine, x, z);
prog.nextIdx = 0;
int[] ys = this.instance.getVisibleBandCache().getOrSchedule(level, engine, x, z);
if (ys != null) {
prog.yList = ys;
prog.nextIdx = 0;
}
}
// defer processing to global prioritized loop
}
@@ -139,8 +142,13 @@ public class PlayerLodTracker {
var prog = state.sentColumns.get(key);
if (prog == null) continue;
if (prog.yList == null) {
prog.yList = VisibleBandUtil.computeVisibleBands(level, engine, cx, cz);
prog.nextIdx = 0;
int[] ys = this.instance.getVisibleBandCache().getOrSchedule(level, engine, cx, cz);
if (ys != null) {
prog.yList = ys;
prog.nextIdx = 0;
} else {
continue;
}
}
budget.addAndGet(-processVerticalList(player, engine, cx, cz, prog, budget.get()));
}

View File

@@ -0,0 +1,39 @@
package me.cortex.voxy.server;
import me.cortex.voxy.common.world.WorldEngine;
import net.minecraft.server.level.ServerLevel;
import java.util.concurrent.ConcurrentHashMap;
final class VisibleBandCache {
private final VoxyServerInstance instance;
private final ConcurrentHashMap<Long, int[]> cache = new ConcurrentHashMap<>();
private final ConcurrentHashMap<Long, Boolean> pending = new ConcurrentHashMap<>();
VisibleBandCache(VoxyServerInstance instance) {
this.instance = instance;
}
int[] getOrSchedule(ServerLevel level, WorldEngine engine, int chunkX, int chunkZ) {
long key = (((long) chunkX) << 32) ^ (chunkZ & 0xffffffffL);
int[] ys = cache.get(key);
if (ys != null) return ys;
if (pending.putIfAbsent(key, Boolean.TRUE) == null) {
this.instance.getThreadPool().execute(() -> {
try {
int[] result = VisibleBandUtil.computeVisibleBands(level, engine, chunkX, chunkZ);
cache.put(key, result);
} finally {
pending.remove(key);
}
});
}
return null;
}
void invalidate(int chunkX, int chunkZ) {
long key = (((long) chunkX) << 32) ^ (chunkZ & 0xffffffffL);
cache.remove(key);
pending.remove(key);
}
}

View File

@@ -21,6 +21,7 @@ public class VoxyServerInstance extends VoxyInstance {
private final DirtyUpdateService dirtyUpdateService;
private final PlayerLodTracker playerLodTracker;
private final VisibleBandCache visibleBandCache;
public VoxyServerInstance(MinecraftServer server) {
super();
@@ -35,6 +36,7 @@ public class VoxyServerInstance extends VoxyInstance {
this.dirtyUpdateService = new DirtyUpdateService(this);
this.playerLodTracker = new PlayerLodTracker(this);
this.visibleBandCache = new VisibleBandCache(this);
// Start a service to tick the dirty service
this.threadPool.serviceManager.createServiceNoCleanup(() -> this.dirtyUpdateService::tick, VoxyServerConfig.CONFIG.dirtyUpdateDelay * 50, "DirtyUpdateService");
@@ -110,4 +112,8 @@ public class VoxyServerInstance extends VoxyInstance {
public UnifiedServiceThreadPool getThreadPool() {
return this.threadPool;
}
VisibleBandCache getVisibleBandCache() {
return this.visibleBandCache;
}
}