
[Bug]在整合包SevTech中会导致游戏无法进入世界
Yesterday17 opened this issue · 10 comments
JECh版本: JustEnoughCharacters-1.12.0-2.2.2.jar
SevTech版本: 3.0.6 (Release)
控制台并没有特殊的日志输出,但是会卡在Loading Terrarian那里。
最后一条日志是和JEI有关的,移除JECh后恢复正常。
怀疑是和GameStage的兼容问题。
@Towdium 应该可以 我给的8G 已提交内存一直没满
从任务管理器来看,卡住之后的GPU占用一直为0%,且保持CPU占用基本不变。
从F3来看,卡住之前的内存占用只有3000MB不到。
下面是节选的日志,我觉得应该就是和GameStage(ItemStage)的冲突问题了。
[20:11:17] [Netty Server IO #1/INFO] [gamestages]: Syncing data for Yesterday17 requested.
[20:11:17] [main/INFO] [journeymap]: Custom modded block handling enabled for bibliocraft
[20:11:17] [main/INFO] [net.minecraft.advancements.AdvancementList]: Loaded 75 advancements
[20:11:17] [main/INFO] [gamestages]: Syncing recived for Yesterday17
[20:11:17] [main/INFO] [Item Stages]: Syncing 16145 items with JEI!.
[20:11:32] [Server thread/INFO] [net.minecraft.network.NetHandlerPlayServer]: Yesterday17 lost connection: 连接超时
[20:11:32] [Server thread/INFO] [net.minecraft.server.MinecraftServer]: Yesterday17退出了游戏
[20:11:32] [Server thread/INFO] [net.minecraft.network.NetHandlerPlayServer]: Stopping singleplayer server as player logged out
大概发现问题了
itemstage有个功能是把禁用的物品从jei物品列表中移除
这个过程会调用到搜索树来寻找对应的物品
jei原来的实现几乎是不需要消耗时间的(是的,jei的实现全部用的缓存,所以不用遍历)
但是jech的实现实际上需要遍历整个物品列表(对于原版大约是2ms完成一次遍历)
像这种巨型整合包遍历一次可能会超过100ms (i5 4200H 实测50ms左右)
然后这两个包大概要移除上千个物品
也就是说在读图的时候会执行上千次搜索
大概就要花几百秒这样子
所以大概率是性能问题 算是以前没有考虑过的情景
我想想怎么修...
临时的方案是在执行特殊搜索的时候使用基于hash的全字匹配(常数级)
在平时用的时候再切换回来
虽然现在搞点小把戏黑过去可能还算可行
根本方法还是优化算法到常数级啊(不可能的)
@Yesterday17 在加载的时候不要动MC窗口 加载过个10分钟会加载完,不被T出游戏
然后在日志中会多一条类似
[10:14:33] [main/INFO]: Receiving (new or changed) Player Data for player aallggg.
[10:14:33] [main/INFO]: Loaded 24 advancements
[10:14:34] [main/INFO]: Syncing recived for aallggg
[10:14:34] [main/INFO]: Syncing 3744 items with JEI!.
[10:14:34] [main/INFO]: Ingredients are being removed at runtime: 3744 net.minecraft.item.ItemStack
[10:21:16] [main/INFO]: Finished JEI Sync, took 402105ms. 3744 hidden, 0 shown.
同步时间爆炸。
我在玩modern skyblock3的时候出现这个问题的
@alg1988 方法还是有的,就是要黑的地方多一点...
@Towdium 大佬加油!
@Yesterday17 这个不能从 Game Stage 切入,因为运行时隐藏本身是 JEI 的特性,就算 Game Stage 的调用可以修复,其他 mod 调用的时候还是会有问题。
最终的方法是检测 stacktrace,如果调用的来源是 JEI 的特定方法,就使用 JEI 原来的实现,如果是在进行列表搜索,再使用遍历搜索。
顺便把遍历的性能再次优化了,现在的话就算用遍历搜索我这边也能正常进游戏了,虽然会卡一两分钟。
文件我发到 curse 了,如果还有问题的话贴在这个 issue 后边就好。
稍微更新一下进度,昨天943说有人更新之后依然进不了存档,我当时在自己机器上测试了,发现居然我自己也进不去(皮)。当时我以为是我传错文件了,后来发现事情并没有那么简单。
出现这个问题的是 2.3.0 版本,修复在 2.3.1 版本。前面说到 2.3.0 用了 stacktrace 来检测 jei 调用的来源,实际上是匹配了方法名“findMatchingElements”,但是这是基于 jei-1.12.2:4.9.1.168 的实现做的。后来发现相关代码 jei 刚刚重写过,老版本用的是“removeIngredient”,加上之后对于老版本 jei 的兼容就正常了。目前我还不会建议大家手动升级整合包里的 jei 版本,我之前尝试了一下问题很多。
至于 2.3.0 版本为什么有的人就能正常进游戏了。这是因为这个版本显著优化了搜索性能,所以如果你的配置很好的话,即使用遍历也足够快了。测试显示windows下边可能性能更好,原因可能是多线程管理策略的不同。943那边大概是半分钟左右完成遍历。
这个匹配逻辑之后又改了,之前“findMatchingElements”和“removeIngredient”是用来匹配内部搜索,在内部搜索的时候就使用 jei 原生实现。最新的实现用了“getSearchResults”(新版 jei)和“search”(老版 jei),只在玩家搜索列表的时候调用拼音搜索,这样我估计能再过滤掉一些潜在的兼容性问题。