冰火传说内存修复

冰火传说内存修复

使用弱引用缓存和无分配状态查询减少冰与火的内存泄漏和实体tick开销。

性能

📖 模组说明

冰与火(Ice and Fire) 会给游戏中的每一个生物实体(包括动物、怪物和村民)附加一个“状态数据包”,用于追踪冰冻、锁链、塞壬魅惑等效果。问题是——绝大多数实体根本用不上这些功能,但它们仍然一直携带完整的数据包,而且游戏每 tick 都必须查询一次。

结果是:内存开销高,且产生了不必要的性能消耗。

这个模组做的正是这件事:消除不必要的内存占用,缩短查询路径。

简而言之:内存减少约 20%,性能提升约 7%。


⚙️ 工作原理

1. 缓存查询结果——不再走弯路

当实体第一次需要其状态数据时,会正常进行查询。之后,结果会直接存储在实体自身上。下次访问时,直接命中——不再需要遍历全局注册表。

2. 仅在需要时创建——不提前分配

原本,每个实体无论是否会用上,都会立即分配 4 个对象(锁链、魅惑、腐蛋、杂项)。优化后,只在真正需要时才会创建对象。普通动物/怪物/村民永远不会分配这些不必要的对象。

3. 读仍是读,写仍是写

只读路径使用一个共享的空对象,永远不会生成新数据。只有实际修改状态的路径才会创建专属数据。

4. 状态为空时释放,只保存关键数据

当状态恢复为空时,其对应的对象会立即释放。NBT 只保存有意义的数据。完全兼容旧存档——可以放心升级。


📊 优化结果

测试方法:使用 Spark heapsummary,相同整合包、相同种子,探索 5 分钟。

指标 未优化 优化后 提升幅度
冰与火相关内存 382 KB 272 KB -28.7%
状态数据包内部内存 169 KB 72 KB -57.0%
每个实体的状态数据开销 约 220 B 约 96 B -56.1%
4 个懒加载子对象总数 3,080 17 -99.45%
JVM 已用堆内存 4.13 GiB 3.57 GiB 约 -478 MiB

🕹️ 6 小时游戏对比

相同整合包、相同渲染距离和实体距离。TPS 稳定在 20。在探索和基地活动之间交替进行。

指标 未优化 优化后 差异
每 tick 查询次数 数亿次全局查找 直接本地缓存读取 大部分查询被消除
JVM 已用堆内存 约 6.2 GiB 约 4.9 GiB 约 -1.3 GiB