fix: improve threaded world compatibility and chunk reads in 1.1.15
Add regression tests and per-dimension progress diagnostics. Document the unresolved C2ME random-initialization redirect conflict.
This commit is contained in:
1 parent
74cae0b581
commit
32b11aee87
42 files changed
+1506
-381
No files matched your search
@@ -42,9 +42,59 @@ Dimensional Ripper 是一个基于 **NeoForge 1.21.1** 的多线程维度并行
|
||||
- NeoForge **21.1.x**
|
||||
- JDK **21**
|
||||
|
||||
## ⚠️ 兼容性警告
|
||||
## ⚠️ 兼容性说明
|
||||
|
||||
> **不兼容警告**:本模组**不建议与任何其他多线程优化模组或跨维度交互类模组同时使用**。经实际测试,与这类模组共同加载会发生冲突并导致游戏崩溃。若需使用本模组,请单独加载,或移除其它多线程优化模组 / 跨维度交互模组。
|
||||
**已知未修复问题(1.1.15)**:与 C2ME 的 `c2me_fixes_worldgen_threading_issues` 同时加载时,双方对 `Level` 构造器内随机源初始化的 `@Redirect` 冲突,可能导致启动失败。日志已确认 C2ME 优先级 1100 的重定向覆盖本模组优先级 1000 的 `modzuozhi_threadSafeRandom`,继而触发注入检查失败。当前源码尚未包含此兼容修复,不能视为可直接部署的稳定版。
|
||||
|
||||
1.1.15 针对 Sable 碰撞查询期间反复创建实心占位区块的问题:
|
||||
|
||||
- 删除 `ModZuozhiSolidChunk`。并行子任务的 `getChunk(..., required=false)` 在区块缺失时返回 `null`,不再伪造“已加载”结果、不分配区块段,也不触发加载/生成。已有区块仍返回当前活动对象。
|
||||
- `required=true` 的缺失 FULL 区块与缺失其它状态统一快速失败,并关闭后续细粒度并行;不会等待正处于屏障的维度线程,也不在部分执行后重跑同一个实体。
|
||||
- 实体预计移动包围盒(外扩 1 格)涉及未加载区块,或扫描跨度超过 8 个区块时,在实体批提交前交所属维度线程串行执行;已加载区域仍保留并行。此预检不是对任意模组远距离查询的保证,遗漏的必须加载请求仍由上一条保护。
|
||||
- 每个超时阶段只输出一次详细线程栈,限服务器/本模组非空闲线程;后续保留简短等待信息。超时不会强行放走仍在操作世界的任务。
|
||||
|
||||
隔离 NeoForge 21.1.244 / Java 21 运行测试:两条实际子任务共执行 60 万次缺失查询、40 万次已加载查询,确认返回值/对象身份、区块数量不增加且并行未降级;验证缺失 FULL/EMPTY 必须加载请求快速失败,加载区域实体并行、超大移动范围实体串行且不重复执行。主线程交接、水流计划刻和维度完成进度测试同时通过。测试中的一次 FaultGuard ERROR 是必须加载失败用例主动触发并在测试中复位,不代表正常运行需要复位。运行方式:`gradlew runServer -PinteractionRegression`,仅用于隔离测试世界。
|
||||
|
||||
本次未运行用户完整服务端整合包(尤其其额外的 Sable Chunk Guard 1.0.0);以上不是完整飞行器/区块发送验收,也不宣称此前 DriveByWire 并发异常已修复。请在存档副本测试,不直接用于正式服。
|
||||
|
||||
1.1.14 增加每维度进度监控:`/dimensionalripper status` 列出所有已创建维度循环的实际完成 TPS(约 10 秒滚动窗口,100ms 分桶)、工作 MSPT 均值/最近值、当前 Tick 持续时间、距最近成功完成时间及失败 Tick 总数。TPS 不再由工作耗时推算,也不钳制到 20;没有新完成时约 10 秒内降至 0,当前 Tick 或无完成时间超过 1 秒单独提示,提示不等于断定死锁。暂停/停止显示状态和 `—` TPS;恢复后的窗口包含暂停时间,约 10 秒后更新完毕。无采样不显示 20。统计随维度循环销毁,不跨存档复用。
|
||||
|
||||
工作 MSPT 含玩家包处理、主线程交接等待和世界工作,排除末尾区块队列轮询;完成记录在整个循环归还世界所有权后写入。世界 Tick 抛异常不计成功完成;细粒度内部自行捕获的错误仍应结合故障状态判断。这些指标描述执行进度,不能证明水流、组装等游戏逻辑正确,也不修改 Carpet 的 HUD。
|
||||
|
||||
1.1.13 为水流问题的**诊断版,不宣称修复停流**。`flowstatus` 改为优先检查准星所指的 8 格内方块/水源,报告实体加载状态、LevelTicks 完整执行条件、最近调度时间、该区块队首计划刻的位置/剩余时间和调度索引。此前 1.1.12 仅显示玩家区块状态及全维度计数,不能据此判断同两项流体任务一直被卡住。本版不绕过实体加载门槛、不重排计划刻、不改写用户存档。
|
||||
|
||||
1.1.12 候选修复:Simulated 的 AssemblePacket(组装/拆解)和 Create 的 BlockEntityConfigurationPacket(包含转速 ValueSettingsPacket)先进入所属维度安全点,再借用服务器主线程执行原处理器。避免维度线程接管期间,主线程 getBlockEntity 返回空值而请求静默失效;保留原处理器的距离和权限检查,排队后换维度/离线则丢弃请求。其余维度继续运行,不全局关闭并行。
|
||||
|
||||
隔离运行测试 `InteractionFlowRegression` 验证了真实 ServerLevel 中的独占主线程方块实体读取,以及放水后的计划刻扩散。测试不加载 Create/Simulated,不能代替完整整合包的实际拉杆、转速和拆解验收;报告的整合包水流停滞尚未复现、未宣称修复。可站在问题水源附近间隔数秒执行两次 `/dimensionalripper flowstatus`,获取世界时间、区块更新条件和计划刻数量;诊断只应用户请求输出,不持续刷日志。
|
||||
|
||||
1.1.11 修正:加载界面的暂停状态不再停止维度循环。暂停交接移到服务器线程,在原版暂停保存之前等待在途维度 tick 完成,并继续处理 Sable 回调;已暂停且完全空闲的维度将区块处理权交还服务器主线程。调度入口与暂停共用同步保护和代次校验,防止取消后的旧任务在恢复时重复启动。
|
||||
|
||||
验证:Lithium 0.15.3 + Sable 2.0.5 临时服务端完成 10 次暂停状态下的真实 ServerPlayer 构造、同步生成新区块、恢复循环,以及 10,000 次运行中区块请求,细粒度保持开启。纯 Java 测试覆盖加载/登录暂停条件及在途/空闲所有权。服务端测试不加载客户端暂停 Mixin,因此不能替代完整 StarLight 单机进世界、ESC 暂停及飞行器验证。临时测试停机时仍记录 Sable 等待被中断的异常,不能将本测试描述为全程无错误。
|
||||
|
||||
1.1.10 修正:1.1.9 在 `getChunk` 入口检查 `mainThread` 后才进入原版方法;维度 worker 可在两次检查之间接管,导致真正服务器线程仍落入原版阻塞 `join`,同时 Sable 排队等服务器线程。现在维度循环启动后,外部服务器区块请求一律通过 `tell` 排队,等待期间处理服务器回调;只有明确暂停了维度 worker 的同步 Sable/玩家交接阶段才允许直接读取。维度异常也不再强行清空仍有区块请求的线程队列。
|
||||
|
||||
本次在 Lithium 0.15.3 + Sable 2.0.5 的临时服务端测试了 10,000 次 server-post-tick 同步区块请求,未卡死且细粒度保持启用,保存退出完成。测试夹具保留于 `tests/integration/ChunkHandoffRegression.java`,不进入发布 jar;完整 StarLight 客户端整合包尚未验证。
|
||||
|
||||
1.1.9 修正:
|
||||
|
||||
- 子任务屏障改为按完整提交阶段计数,修复“先完成一批、随后又提交任务”时一次性 latch 提前放行的问题。超时和中断均不再允许在任务未完成时继续下一阶段。
|
||||
- 10 秒是诊断阈值,不是正常加载预算;超时后关闭后续细粒度阶段,但保留当前维度所有权并记录完整线程栈、锁持有者、阶段和池状态。真正卡死的任务不会被此机制强行解锁,仍需根据诊断定位。
|
||||
- 实体查询先在锁内收集结果,再在锁外执行回调,避免回调移动/删除实体导致读锁升级死锁。
|
||||
- 子任务读取非 FULL 区块也走已就绪路径;必须同步生成时明确报错并关闭后续细粒度并行,避免等待正在等待自己的维度线程。
|
||||
- **Lithium 环境下村民改在所属维度线程执行**:实测 65 村民并行查询 POI 可写坏 Lithium 的 `ListeningLong2ObjectOpenHashMap`。这是定向限制,Sable 物理主线程桥接、其它生物、方块实体和区块环境的并行开关不因此关闭。
|
||||
- Lithium 的实体分类缓存添加同一实例上的读写同步,并返回快照,修复碰撞查询绕过 section 锁后与实体移动并发修改分类集合的问题。
|
||||
|
||||
等待逻辑回归测试:`tests/TaskBarrierRegression.java`(提交间隙、超时、中断、可见性、2 万次并发完成)和 `tests/ManagedFutureAwaitRegression.java`。这些测试与小规模 Lithium + Sable 临时世界测试不替代完整整合包及真实飞行器验证;旧日志缺少子任务栈,无法唯一确定旧 10 秒超时的具体阻塞点。
|
||||
|
||||
1.1.8 修正:真实服务器主线程同步等待区块 Future 时,使用服务器事件循环的 managedBlock 继续处理回调,避免主线程等待区块、维度线程等待物理/玩家主线程回调的循环等待。区块任务仍由原区块执行器处理。独立等待关系回归测试位于 `tests/ManagedFutureAwaitRegression.java`;它验证回调归属、完成、异常和取消,不替代整合包内的进服及飞行器测试。
|
||||
|
||||
1.1.7 修正:加载 StarLight Extra 时,玩家连接 Tick(包括玩家 Tick 事件和断开清理)同步交回服务器主线程,对应维度等待完成后继续。区块反序列化恢复使用原有区块执行器,避免后台反序列化同时写入 Lithium 的 POI 存储。其它维度及细粒度并行开关不因此关闭。这是针对已观察到异常的修补,编译或空服启动成功不代表完整整合包、玩家交互和飞行器压力测试已通过。
|
||||
|
||||
> **Create: Aeronautics / Sable**:1.1.5 起内置主线程桥接。Sable 的物理子世界 Tick 同步交回真正的服务器主线程,完成后维度 worker 继续运行。已开始的物理阶段必须结束后才能归还所有权,不能通过超时强行中断。可通过 `/dimensionalripper status` 确认桥接及 Lithium 村民限制。
|
||||
>
|
||||
> **Lithium**:1.1.6 起会优先保留 Lithium 的实体移动碰撞注入,避免双方争抢同一调用点导致启动崩溃。本模组的实体互推关闭仍会生效;移动碰撞查询交由 Lithium 优化。
|
||||
>
|
||||
> 其它多线程优化模组或跨维度交互类模组仍不建议与本模组同时使用;尚未建立专门兼容路径的组合可能发生冲突。
|
||||
|
||||
## 指令
|
||||
|
||||
|
||||
Reference in new issue
Block a user