Skip to content

⚡ 性能优化与队列节流引擎

Agrarian Reform 专为高负载服务器精心设计,即便承载万人级农业巨型农场也不会引起瞬间卡顿、看门狗超时或 TPS 下降。


📊 性能技术指标信息框

PropertyValue
Global Throttling BudgetCROPS_PER_TICK = 5
Queue Implementationjava.util.concurrent.ConcurrentLinkedQueue
Sub-Chunk Palette FilterhasOnlyAir() & maybeHas(AgrarianCropRules::isCropBlock)
水分检索机制切比雪夫同心环方块扫描 ($r=1 \to \text{maxRange}$,临近水源极速跳出)
靴子优化防抖赤足极速快速判断 ($0.0001\mu\text{s}$,跳过开销巨大的附魔查询)
运行诊断日志静态 SLF4J 记录器,受瞬态游戏规则 agrarian_reform:debug_mode 管控

🧠 架构设计与快速跳过流水线

┌─────────────────────────────────────────────────────────────┐
│                    CHUNK LOAD SCAN EVENT                    │
│ Palette Pre-Filter: section.hasOnlyAir() & maybeHas()       │
│ Rejects 85%+ empty non-crop sub-chunks in O(1) time         │
└──────────────────────────────┬──────────────────────────────┘


┌──────────────────────────────┴──────────────────────────────┐
│             ConcurrentLinkedQueue<CropUpdateTask>           │
│ Lock-free thread-safe task buffer                           │
└──────────────────────────────┬──────────────────────────────┘


┌──────────────────────────────┴──────────────────────────────┐
│                  ServerTickEvents.END_SERVER_TICK           │
│ Polls at most 5 tasks per tick                              │
│ Updates block states smoothly across consecutive game ticks │
└─────────────────────────────────────────────────────────────┘

为什么每刻处理 5 处作物?

当玩家在卸载包含 10,000 处作物的农场 24 小时后重新加载时,若在一刻内同时触发 10,000 次方块状态更新,会导致服务器产生超过 1000ms 的严重卡死。

通过无锁并发地以每刻 5 处作物的速率分摊更新:

  • 区块加载期间服务器 TPS 依然牢牢稳固在 20 TPS
  • 10,000 处作物在后台平滑过渡 2,000 刻(约 100 秒)即可全部追赶完毕,丝毫不影响正常游玩与网络延迟。

🏎️ 核心快速跳过与算法优化

  1. 子区块调色板快速排查:取代逐一扫描区块内 $98,304$ 个方块坐标的方式,CropScanner 直接检索子区块调色板。若一个 $16 \times 16 \times 16$ 的子区块不含农业方块,整段区域将在 $0.0001\mu\text{s}$ 内瞬间跳过。
  2. 切比雪夫同心环由内向外扫描:耕地水分计算由最近的方形环($r = 1 \to \text{maxRange}$)逐步外扩。由于多数耕地紧邻水源($r=1$),在第一环命中后即刻判定完成,无需遍历全部 $17 \times 17$ 位置。
  3. 赤足踩踏防抖:实体接触耕地时,GrowthHelper.hasSoftStep() 首先检查脚部装备槽是否为空。若为空,则彻底跳过复杂的 NBT 附魔遍历。
  4. 最大成熟期立即跳出:在高倍率生长循环中,一旦作物达到最大成熟度,循环即刻终止,避免无效的方块状态写入。

💾 零磁盘写入保障与脏状态维护

  1. 只读区块表面快速扫描:初始加载扫描 100% 只读,绝不调用 LevelChunk.setBlockState(),保持区块内部 unsaved 标识为 false
  2. 精细化方块状态写入:在 ContinuumManager.processCropUpdate 中,仅当阶段增量 $\Delta \text{age} > 0$ 时才调用 level.setBlock()
  3. 原生零磁盘 I/O 保护:未改动区块保持 unsaved == false,Minecraft 原生 ChunkMap.save() 会直接跳过 NBT 序列化与 .mca 写入($0\text{ 磁盘写入开销}$)。

See also: 时空连续体 (离线生长模拟), 水动力学与灌溉系统, and 架构设计与 Mixin 注入参考.

Official documentation & web portal for Dasik Igaijinn mods.