perf(prefetch): ChunkPrefetcher 深度 6→10 + 前方扇面 ±1,缓解冲刺进新区块卡顿

观察:沿已生成区块边缘扩展极快,冲进大片未生成区则卡(1300mspt)。
根因:维度线程 tick 中 getChunk 未加载区块 → mainThreadProcessor.managedBlock park
等生成;冲刺速度快时预取前沿(view+6)不够,生成跟不上 → park 久 → tick 卡 →
主线程 payload 全局独占相位跟着等。

改动:
- PREFETCH_DEPTH 6→10(前方多预取 4 格,给生成管线更多提前量)。
- 新增 PREFETCH_FAN_HALF=1:除正前方外,垂直轴左右各预取 1 列,覆盖拐弯/斜向移动。
- 沿已生成边缘无额外开销:hasChunk 命中即跳过,不重复下 ticket。
- 纯增益,可回退(ENABLED 开关 + 常量改回)。
This commit is contained in:
Xiao-no-love committed 2026-10-13 21:05:24 +08:00
1 parent a7afed5311
commit 1ab215dc72
1 file changed
+14 -4
@@ -48,8 +48,12 @@ public final class ChunkPrefetcher {
/** 预取重算间隔(tick),降低每个玩家的逐 tick 开销。 */
private static final int PREFETCH_INTERVAL_TICKS = 5;
/** 预取深度:在玩家视距之外,再向前预取的区块数(收敛为 4~6 格,避免过度预取浪费算力)。 */
private static final int PREFETCH_DEPTH = 6;
/** 预取深度:在玩家视距之外,再向前预取的区块数。冲刺进入大片新区块时,生成速度是瓶颈,
* 加深到 10 格给生成管线更多提前量(沿已生成边缘几乎无额外开销:hasChunk 命中即跳过)。 */
private static final int PREFETCH_DEPTH = 10;
/** 预取扇面半宽:除正前方外,额外预取左右各 ±1 列(覆盖拐弯/斜向移动)。 */
private static final int PREFETCH_FAN_HALF = 1;
/** 自定义预取 ticket:FULL 级别 + 有限存活时间。 */
private static final TicketType<Unit> PREFETCH_TICKET =
@@ -127,10 +131,16 @@ public final class ChunkPrefetcher {
int simDist = level.getServer().getPlayerList().getSimulationDistance();
int from = viewDist + 1;
int to = viewDist + PREFETCH_DEPTH;
// 主轴 = 移动方向 (dirX,dirZ)(二选一非零);垂直轴 = 主轴旋转 90°。
int perpX = (dirX != 0) ? 0 : 1;
int perpZ = (dirX != 0) ? 1 : 0;
int prefetched = 0;
// 扇面预取:沿移动方向深度 [from~to],垂直轴左右各 ±PREFETCH_FAN_HALF 列(覆盖拐弯/斜向)。
for (int k = from; k <= to; k++) {
if (prefetch(source, chunk.x + dirX * k, chunk.z + dirZ * k)) {
prefetched++;
for (int f = -PREFETCH_FAN_HALF; f <= PREFETCH_FAN_HALF; f++) {
if (prefetch(source, chunk.x + dirX * k + perpX * f, chunk.z + dirZ * k + perpZ * f)) {
prefetched++;
}
}
}
if (state.firstLog || gameTime - state.lastLogGameTime >= 20) {