3l psi 发表于 7 天前

[预热&讨论]雷霆优化mod:超新星爆炸:无限引擎

本帖最后由 3l psi 于 2026-11-2 23:36 编辑

如各位所见,我这个mod的名字很雷霆,但是完全可以相信它的优化效果(

(这是大饼!不要全信!)后记:可以信了,差不太多,但这和你电脑的性能有关在和 FR,VramOpt 强强联合的情况下,预期实现的最终加载速度:260mod,30~50s47~60s加载完。

贴里先讲我将先实现,并且发布测试版的那部分的优化原理。

众所不周知,远行星号在加载的脚本阶段,会现场编译大量代码。以测试结果为例:



(注:此测试结果还加了一堆mod,其中fast rendering可能对此测试结果造成了影响,仅供参考)

每次加载都要现场进行编译,这效率还是太低下了不是么?

老实加载,很枯燥吧?(

我要做的这个优化mod,其功能之一,就是:把这部分实现预编译。一次加载,再也不需要进行现场的编译。

这在mod很多的情况下,节省出来的加载时间看起来还是很可观的。

另一部分优化的思路嘛,过于狂野了,我自己都怀疑能不能做出来,所以这里先按下不表(

后记:是的,确实过于狂野了,也只做出来了一小部分(


全自动电棍 发表于 7 天前

本帖最后由 全自动电棍 于 2026-10-29 23:56 编辑

事实上你游有类似的优化
不难注意到ScriptStore类中存在以下分支

      if (!StarfarerSettings.getBoolean("enableScriptCaching")) {
         sourceClassLoader = new JavaSourceClassLoader(var0, new ScriptSourceFinder(), "UTF-8");
         sourceClassLoader.setDebuggingInfo(true, true, true);
      } else {
         // 注意到这里有一个Cache分支
         sourceClassLoader = new CachingJavaSourceClassLoader(var0, new ScriptSourceFinder(), "UTF-8", new ResourceFinder() {
      // 略...
      }


不过你可以详细讲一讲你的优化思路,或许可能比原版游戏更好

另外加速编译这一块据我所知已经有两个项目了,这其中甚至不包括fr,大coremod时代来临力,,,

3l psi 发表于 6 天前

全自动电棍 发表于 2026-10-29 23:54
事实上你游有类似的优化
不难注意到ScriptStore类中存在以下分支



好嘛,我犯蠢了,逆向不完全等于完全不逆向(




但是a圣是这么写的注释,而且这选项默认关闭来着:
# disabled for now, causes issues with subsequent runs if game is shut down during startup
"enableScriptCaching":false, # caches compiled scripts in saves/cache, faster startup time after first run



说明这玩意设计的还是有点问题(直接 FileOutputStream写到最终路径,那加载一半关了可不“cause issues”么;没有并发仅单线程,理论上不兼容FR)

而我要设计的东西,采用 tmp + ATOMIC_MOVE + CRC 实现原子写,可以解决a圣遇到的问题

此外, FR 的目标是多线程编译,但原版的 CachingJavaSourceClassLoader 是单线程,FR的解决方案是写了个更快的 loader,代价是理论上a圣写的那个功能用不了/失效(我懒得去复现了,太晚了)

我绝赞开发中的此项目不碰 loader ,而是在它已有的 bytecodeCache 上做 preload,这会使得它原版能用,比A圣写得好;还兼容 FR,可实现加载速度优化叠叠乐。

但我高估了我做的项目,其部分实现的含金量了,没想到a圣也想到了能这么做(

全自动电棍 发表于 6 天前

本帖最后由 全自动电棍 于 2026-10-30 00:28 编辑

3l psi 发表于 2026-10-30 00:17
好嘛,我犯蠢了,逆向不完全等于完全不逆向(



噢

我这边正在研究如何将Janino的编译后端换成ECJ并有限的实现一些优化
原理是通过重新实现游戏使用的Janino类达成(ABI兼容)

而因为是ABI兼容的原因原来的类可以直接当成一个壳子,实现可以委托到别的什么上,这就给搞一些优化提供了空间(顺带一提Janino的缓存源类加载器写的也有问题来着)

有意愿的话可以交流一下

Edit:
顺带一提,fr的多线程加载好像是包装了一下原始的Janino SourceClassLoader来着,希望我写的这个玩意不会炸

Edit2:
游戏仅使用了以下这些类,所以重新实现起来并没有特别难

[*]org/codehaus/janino/CachingJavaSourceClassLoader
[*]org/codehaus/janino/JavaSourceClassLoader
[*]org/codehaus/janino/util/resource/Resource
[*]org/codehaus/janino/util/resource/ResourceCreator
[*]org/codehaus/janino/util/resource/ResourceFinder


3l psi 发表于 6 天前


冒完烟了,冒得我火冒三丈啊(

这部分实现的实际优化效果被我严重高估了。

在我使用的260mod压力测试环境里, 日志里有 15,070 条 `Compiling script`。我一开始以为,“wow,全都是现场编译,全都是优化空间”

查下去发现这行是 FR 的 ScriptStore.loadScript() 在 loadClass 之前打的,它先打日志,后加载

也就是说,就算类从 mod jar 里加载成功,并没有在加载现场进行编译,也会留下一条 "Compiling",日志里充斥海量不可名状之物

真实入口是 MultiThreadedJaninoClassLoader.findClass,我的 260mod 环境实测 13,029 次调用。

其中 1,765 次命中 bytecodeCache,剩下 11,264 次 miss。

那这些miss又是怎么回事呢???

还是FR引入的!

反编译 `com.fs.starfarer.campaign.rules.oOOO` ,找 getCommandClass 的实现

对比一下原版和FR:

原版: Class.forName(name, false, ScriptStore.<javaSourceClassLoader>.getParent()) → 走 URLClassLoader(装 mod jar 的那个),不碰 Janino

FR: BytecodeFileTransformer 把整个方法换成 com.genir.renderer.overrides.Expression 新实现用 getScriptClassLoader().loadClass(name) → 走 MultiThreadedJaninoClassLoader,每次失败都打进 findClass


所以这 1.1w+ 次探测,实际在原版根本不存在——是 FR 的结果,它们实际上零编译成本


给FR提了Issue:github.com/Halke1986/starsector-render/issues/13

我在调试过程中呢,还搓了个反向优化

我加了个 SourceOracle:判断某个 miss 的类到底有没有 .java 源,它跑在主加载线程上,而它每次扫一遍都要花13~17秒左右

缓存理论省了7秒,我写的诊断代码直接吃17秒,倒欠10秒......

后来被我扒出来修掉了。

此外,测试的数据非常不稳,连不加此mod的基线也在变(这和我测试用的基座也打了优化mod似乎脱不开关系,我的错),从1.5~64.7s的优化效果都有

ai 猜测的是 windows 的文件系统缓存发力了,也因此纯应用层的收益我还没测到。

好消息还是有的,技术路线成立,preload 3s → 7ms,但理论上,这部分整体优化的收益上限,会从 20~25s 变成 7~14s。

但我的优化还没有止步在这里。

也就是说,是孢子哥赢了(?

下一话!向法线贴图!

3l psi 发表于 6 天前

全自动电棍 发表于 2026-10-30 00:24
噢

我这边正在研究如何将Janino的编译后端换成ECJ并有限的实现一些优化


下面内容是我用 Claude code 对着 jar 一条条分析的,细节我应该是第一时间答不上来(摸鱼了。深空当铺,好玩!),但每条都给了证据位置,方便你可以直接复现或者打脸。

一、你那 5 个类是准的

扫 starfarer_obf.jar 全部 class 的常量池、按 org/codehaus/janino/ 去重,结果就是你列的那 5 个
(CachingJavaSourceClassLoader、JavaSourceClassLoader、Resource、ResourceCreator、ResourceFinder)。
补两点:

- fr.jar 只引用其中 2 个:JavaSourceClassLoader、ResourceFinder。装 FR 的环境里
CachingJavaSourceClassLoader 根本不会被构造——FR 的 ScriptStore 把整个 enableScriptCaching 分支覆盖掉了。
- 你重写的 ResourceFinder / Resource / ResourceCreator 必须和原版方法描述符完全一致,因为游戏侧
也实现了它们:com.fs.starfarer.loading.Objectsuper extends ResourceFinder、ScriptStore$1 extends
ResourceFinder、ScriptStore$2 implements ResourceCreator。ABI 是双向的,不只是"游戏调用 Janino"。


二、两个版本也许都得过

vanilla 的 janino.jar 是 2.7.8(manifest 里写着),Mikohime 是 3.0.12,同一份 fr.jar 要在两者上都跑。
我 javap 逐成员 diff 了这 5 个类加 AbstractJavaSourceClassLoader:删除 0、签名变更 0,3.0.12 只多 3 个
私有/静态成员(compiledUnitCompilers、$assertionsDisabled、static {})。所以单套 shim 覆盖两版是可行的。


三、FR 到底是怎么包的(你 Edit 里那条)

- MultiThreadedJaninoClassLoader extends ClassLoader,内部 ThreadLocal<JavaSourceCompiler>,每个线程一个实例。
- JavaSourceCompiler extends JavaSourceClassLoader:先走 (ClassLoader, ResourceFinder, String) 三参构造器,
再 setDebuggingInfo(true, true, true);它覆盖的是 getBytecode,里面调 protected 的 generateBytecodes(String)。
- 所以你的 shim 只要守住三件事就接得住:那个三参构造器;setDebuggingInfo 必须真实生效(否则 mod 报错
就没行号了);generateBytecodes 保持 protected、返回 Map<String, byte[]>,且 key 是点分二进制名
(Janino 的 ClassFile.getThisClassName() 会把 / 换成 .,FR 直接 bytecodes.get(name))。
- 一个坑:new JavaSourceFinder() 这个类磁盘上根本不存在。fr.agent.jar 的 Transformations 里有一张
obfuscation 映射表,把 com/fs/starfarer/loading/JavaSourceFinder 指到 com/fs/starfarer/loading/Objectsuper。
运行时你拿到的是游戏的 Objectsuper,别按类名或包路径做假设。


四、这个接口的语义有两个坑,建议先确认

- generateBytecodes(name) 不是"编译这一个类",而是把该 loader 里所有还没编译过的 UnitCompiler 全编一遍
(3.0.12 用 compiledUnitCompilers 记住编过的,2.7.8 是每次调用现建一个局部 Set)。你的 ECJ 后端必须
复现"一次调用产出整个编译单元的所有类(含内部类)"这个语义。
- 反过来,某个单元编译失败会让后续每一次调用都再撞上它(失败的 unit 一直留在
JavaSourceIClassLoader.getUnitCompilers() 里)。这就是我这边观察到的"坏类传染":一个坏文件能把
同线程后面所有类一起带崩。如果 ECJ 侧能做到"失败不污染别人",这条比速度值钱得多。


五、你说的缓存源类加载器的问题

应该就是这个:vanilla ScriptStore$2.createResource 是 new FileOutputStream(file) 直写最终路径,
没有 tmp + rename;进程在启动期被杀就留下截断的 .class。游戏自己在 settings.json 里写了
"causes issues with subsequent runs if game is shut down during startup",并默认关掉这个开关。
另外它的 deleteResource 还带三重条件(.class 结尾 + 含 "cache" + 含存档路径),基本等于不删。


六、收益天花板可能有限

我在 260 mods 上实测的数(口径不是日志行数):

- Compiling script 一共 15,070 行,但其中 13,350(88.6%)是从 mod jar 命中、根本没编译——parent-first,jar 优先;
- 真正有源码、每次都要编的是 1,667 个源文件,产出 2,113 个 class 条目;
- Janino 单类约 3,380 µs,1,667 × 3,380 µs ≈ 5.6–7.1 s 单线程;FR 是 3 线程并行,摊下来大概 2–3 s 墙钟
(估算,没单独测过)。

也就是说:换编译器能动的预算是冷启动的 2–3 秒,热启动这条路径已经被编译结果缓存吃成 0 了。另外 FR 把
rulecmd 探测改成走 script loader 之后,一次启动会有约 11,264 次"这个名字没有源码"的 generateBytecodes
调用(已给 FR 开 issue #13:https://github.com/Halke1986/starsector-render/issues/13 )。所以 shim 的空路径
必须极快:查不到源就立刻返回 null,别在这条路上做扫描或抛异常——这个数字比编译本身更可能决定成败。


七、我的建议

- 把目标从"更快"改成"更能编 + 不传染"。Janino 2.7.8 连 lambda 都没有(3.0.0 才加);3.0.12 也没有
var / record / sealed(我在 Parser 里找不到这些 token);ECJ 能到新版。这对 mod 作者是实打实的收益,
速度是顺带的。
- 速度这件事请先测再投入:Janino 本来就是为嵌入式快速编译设计的,ECJ 不一定更快,尤其是单类小文件、
每次都要建 name environment 的场景。
- 别整包替换 janino.jar。我扫了 272 个 mod jar,有 3 个直接引用 ScriptEvaluator / ClassBodyEvaluator
(ConsoleCommands 的 RunCode、Nexerelin 的 NexUtils,还有一个捆进去的 recaf)。把 shim 放在 classpath
前部、只 shadow 那 5 个类,其余类继续从原 jar 解析,这些 mod 就不受影响。

3l psi 发表于 6 天前

接下来是大战法线贴图和也许能成的懒加载(后者我认为是很不好搞的,claude code大人救我)

会赢的(

3l psi 发表于 6 天前

法线窗口已成功被我优化掉。

3l psi 发表于 6 天前

260mod环境,目前加载速度被压到了76s

还能凹!

GerBeria 发表于 6 天前

3l psi 发表于 2026-10-30 21:50
260mod环境,目前加载速度被压到了76s

还能凹!

法线这块咱俩撞车了,我是cpu生成消核显gpu大量回读的死机问题,准备做预生成(就差gui了),原生加载逻辑有问题:会全量加载后因为preloadAllMaps=false再全丢掉,我直接在这一步建空纹理,按需懒加载原版就有。

3l psi 发表于 6 天前

GerBeria 发表于 2026-10-30 22:13
法线这块咱俩撞车了,我是cpu生成消核显gpu大量回读的死机问题,准备做预生成(就差gui了),原生加载逻 ...

啊这....

稍等,我审计一下我的技术路线是否与你撞车

也许你的思路更优秀,因为我这边的收益没有预期的那么高,被其它部分吃掉了一半

3l psi 发表于 6 天前

GerBeria 发表于 2026-10-30 22:13
法线这块咱俩撞车了,我是cpu生成消核显gpu大量回读的死机问题,准备做预生成(就差gui了),原生加载逻 ...

我核对了一下:

法线这一块我们是彻底撞车了,

同一个坑:GraphicsLib/cache/*_normal.png,260mods 上 30,378 张

同问题:vanilla 为了拿尺寸把每张缓存图完整 load 一遍,又因为 preloadAllMaps=false 立刻 unload,纯冗余



同解决方案:启动期只登记、按需懒加载,复用原版 !loaded && validToLoad

我今天已经把这一部分全面跑通, 260 mod 测试环境,启动期 30,378 → 0。

但是你那条用cpu预生成避免gpu回读导致死机,我没做,我只把预生成做成了可选项,没考虑太多稳定性相关

至于预生成,我走的是复用 DDS:VOpt 带的 DDSCreator.exe(ispc_texcomp)离线烘 BC7,产物落 DDSCache 的 metadata,运行时由 DDS 覆盖层接管。

有个坑不知道你遇没遇到,我先分享下:直接烘 GraphicsLib 是烘不到的,DDSCreator 会跳过 shaderLib。可行绕法是把这些 PNG 硬链接 staging 到一个普通 mod 的 graphics/ 目录,烘完再把 metadata 里的 ModFolderName / RelativeImagePath 改写回 GraphicsLib/cache。


然后,有一点隐患,这很可能导致后续我们的mod完成开发后,互不兼容:org/dark/shaders/util/TextureData 现在已经有 FR 的 transformer 在改 GL 常量池,我的补丁是第二个改写者,按 GraphicsLib 1.12.1 原 class 的 SHA-256 锁死。如果你改本体,我的补丁会静默 no-op;如果你把 PNG 换成 DDS 或者改名,我的缓存探测是按 31,627 个 *_normal.png 文件名建集合的,会全 miss,同样静默失效。


所以,mapSpriteToMNSWithAutoGen 的 normal 分支最好只留一个 owner,你或者我要动的话,我建议在帖子里先打个招呼



想对齐几件事,不确定的直接让 agent 核:

1. 改 GraphicsLib 本体还是运行时注入(agent / 独立 mod)?
2. "空纹理"是 null 还是 1×1 占位?占位期间法线是缺的还是错的?首次加载前有谁会读宽高?
3. preloadAllMaps=true / invalidateCache / alwaysPreload 这三种情况你怎么退化?
4. 预生成产物是 PNG 还是 DDS、落在哪个目录、体积和增量失效怎么处理、玩家要不要本地先跑一次工具?如果走 DDS,*_normal.png 的文件名保不保留——这条决定我们两套能不能叠叠乐。
5. 你现在的启动时间是多少、什么口径?

GerBeria 发表于 6 天前

3l psi 发表于 2026-10-30 22:46
我核对了一下:

法线这一块我们是彻底撞车了,


1,我表示mixin真的很好用,通过mixin运行时改写,不动磁盘文件。2、3,开关、!invalidatecache、!preloadAllMaps(),只读png头33字节,任一不成立原生真加载。4,法线产物png,dds法线图真的能用?而且懒加载不用也不占内存。多线程双向逐条检。5,-2.1s/-5.6s,缓存加载条9806>9-13且全在主菜单之后,intelCoreultra125h 32g 核显 99modjar。

3l psi 发表于 6 天前

GerBeria 发表于 2026-10-30 23:15
1,我表示mixin真的很好用,通过mixin运行时改写,不动磁盘文件。2、3,开关、!invalidatecache、!preloa ...

对于mixinFR,我看你做的那个暂不支持java28,就没去研究mixinlib及相关路线,不然理论上我们可能撞车撞得更彻底(

对于33字节,woc,天才的主意

我这边的实现是只按文件名 + 长度 ≥ 8B 来建集合,截断的,非 PNG 也会登记懒条目,毛病会推迟到进战斗加载对应法线贴图才会暴露。你的实现比我这里的优雅的多,韩了(

至于DDS,是有点问题,一定程度上是我偷懒了。查了一番,对于法线贴图,正统一点的处理方式是 BC5(两通道 + 重建 Z), BC7 理论能用(我冒烟了,确实能用)但不是最优方案,画质我确实没仔细看,回头我搞个 A/B 盲测

有两个问题:

1.bro,33 字节是校验还是拿宽高建 w×h 占位?我学习一下;

2.织入的是 TextureData.mapSpriteToMNSWithAutoGen 的 normal 分支吧?TextureData 不在 FR 重写的那 29 个游戏类里,但 FR 的常量池改写也会动它(GL 常量重定向)。你的 mixin 是在这次改写之前还是之后应用?我这边 agent 被 SHA 锁逼着必须排在 FR 前面,所以想确认 MixinFR 是怎么排的。


GerBeria 发表于 5 天前

3l psi 发表于 2026-10-30 23:50
对于mixinFR,我看你做的那个暂不支持java28,就没去研究mixinlib及相关路线,不然理论上我们可能撞车撞 ...

就是png文件的开头33个字节,png文件签名和ihdr数据块头部。咱不是graphicslib的法线贴图缓存吗,和fr好像无关诶。目前是原版字节-mixin-fr字节改写,fr字节改写只改写它明确要改的,mixin独立添一个会存活被保留,这是现在的结论。然后回答你的问题是真不容易,要知道我的项目可都是ai跑出来的,我就一测试员。唉!

GerBeria 发表于 5 天前

3l psi 发表于 2026-10-30 23:50
对于mixinFR,我看你做的那个暂不支持java28,就没去研究mixinlib及相关路线,不然理论上我们可能撞车撞 ...

fr直载dds是写死了格式和元数据规定的,游戏原版是不认dds的,而且其他格式的压缩比和压缩时间也有待取舍,目前的基本上是最优解了

3l psi 发表于 5 天前

GerBeria 发表于 2026-10-31 00:04
就是png文件的开头33个字节,png文件签名和ihdr数据块头部。咱不是graphicslib的法线贴图缓存吗,和fr好 ...

没事,不必感到压力爆大,我这个mod也有 claude code 的深度参与。

主要是我担心和我互动的是一个正经工程师,所以我把具体的实现发的很详细(这也大多是agent的功劳)

3l psi 发表于 5 天前

我似乎忽略了另一重问题: FR 更新到 0.97rc2 了,有无可能它把我们俩的活都干了呢

严肃审计中

3l psi 发表于 5 天前

嘶...我该说撞车了吗?

我觉得可以算没撞车

我要适配的话,完全可以,就是工作量有点大

3l psi 发表于 5 天前

3l psi 发表于 2026-10-30 21:50
260mod环境,目前加载速度被压到了76s

还能凹!

70s。

纠正一个统计口径,这是在 Hypernova + FR + Vramopt + jdk28 + 260 mod下跑出的数字

作为对比,之前没有 Hypernova 的基线为 ~90s

3l psi 发表于 5 天前

FR 0.9.7 rc2的性能提升效果十分明显,遗憾的是这次提升非我的mod的功劳

60s

雪夜晴岚 发表于 5 天前

技术跃进(

3l psi 发表于 5 天前

雪夜晴岚 发表于 2026-10-31 12:54
技术跃进(

跑步进入ss秒开时代(笑

3l psi 发表于 5 天前

下一站应该是大战贴图加载,这一部分也是我觉得较为疯狂,也暂时让我摸不着头脑的一部分
理论上,加载速度会再一步飞跃,且我猜测游戏存档前期的帧数会略微更高,但玩一段时间后帧率恢复到无此mod优化水平

3l psi 发表于 5 天前

3l psi 发表于 2026-10-31 01:24
嘶...我该说撞车了吗?

我觉得可以算没撞车


补充,已适配

3l psi 发表于 5 天前

预期下一步还能砍掉 ~5s
fr 目录枚举的大量文件 + dds 元数据
当然,离了这俩mod,此mod的性能优化依然生效,只是这省出来的时间就没有力

洛赛莱 发表于 5 天前

看了你们的交流,开始期待一种优化界的大统一理论。

3l psi 发表于 5 天前

3l psi 发表于 2026-10-31 13:41
下一站应该是大战贴图加载,这一部分也是我觉得较为疯狂,也暂时让我摸不着头脑的一部分
理论上,加载速度 ...

搞错了,是下下一站
目前先砍掉一点蚊子腿

3l psi 发表于 5 天前

洛赛莱 发表于 2026-10-31 15:56
看了你们的交流,开始期待一种优化界的大统一理论。

不知道你说的大一统具体指什么,如果说是mod超级拼装的话,也许会有,也许不会()

我倾向于优化mod还是有好几个,但是我预言,会有一个mod变得社区公认,人人都装,就像早期的mc强绑定optifine一样。

或者压根就没上述的时间线,直接来到mc以钠为首的元素周期表优化时代,多个适用范围不同的优化mod,装什么看玩家心情

洛赛莱 发表于 5 天前

本帖最后由 洛赛莱 于 2026-10-31 17:12 编辑

3l psi 发表于 2026-10-31 17:06
不知道你说的大一统具体指什么,如果说是mod超级拼装的话,也许会有,也许不会()

我倾向于优化mod还是 ...
我是觉得这种涉及游戏引擎层面的东西,最终会产生某种基本的工作方法,变成通用标准。
就像现在的mikohime。这种东西单独分成众多的MOD总觉得不太对劲。

PS:大统一理论GUT是指现实科学界一种理论上存在的将物理学各个理论最终统一的“宇宙理论”,我这里化用了这个概念。

3l psi 发表于 5 天前

理论上又扣掉了6.5s,但是加载时间还是浮动在60s上下...怎么回事呢?

3l psi 发表于 5 天前




点击输入文本

260 mod 测试环境,47秒进主菜单!

GerBeria 发表于 5 天前

3l psi 发表于 2026-10-31 15:53
预期下一步还能砍掉 ~5s
fr 目录枚举的大量文件 + dds 元数据
当然,离了这俩mod,此mod的性能优化依然生效 ...

dds元数据可以二进制化,fr目录枚举可以建索引,但仅限jar,我这里实测普通目录没收益;目录索引还可以再加上权威未命中,但要考虑运行时创建文件在读取的问题,主要是加载时的各类缓存,咱没法穷举。rules合并的索引和权威未命中应该好使。主要是这些我都做完了,收益几秒几秒的;然后你好像一直没提你的测试平台配置,单线程游戏及其要求单核性能和频率;最后再提醒一下别做成你自己的单测试环境专项优化,注意通用性。

3l psi 发表于 4 天前

和 agent 搏斗了半天,剩下的加载速度优化空间吧,其实没啥了....

但是我这里又发现了显存优化空间

理论上能减少 60% 左右的显存占用,让远行星号的显存占用一刀被砍到几百 mb 量级

3l psi 发表于 4 天前

本帖最后由 3l psi 于 2026-11-2 16:49 编辑

已实现基于纹理懒加载的显存占用砍半起步

也许会有人问:啊,孢子哥, VramOpt 不已经爆砍显存占用了么

孩子们,我的项目在这一块是独立乘区,理论上可以和 VramOpt 进行超级叠叠乐(这里保守一点,因为尚未实测拉表对比,尤其是仅 hypernova vs hypernova ,VramOpt 都不装的测试,这块暂时是空白)

理论上完善之后,在和 VramOpt 强强联合的情况下,可以让 260 mod 环境的远行星号显存占用来到常态(包括长时间玩生涯)仅 300 ~ 400 mb

让显存永远不成为远行星号的门槛,即使你用的是核显笔电,无论你加多少 mod

但是捏,目前冒烟只跑到了加载跑通,生涯实测&不加载的纹理直接卸载还在激情开发中

我错了,A圣



而且理论的维护成本,高到难以用语言形容。我预计只会做个 L1 ,而 L1 的价值更贴近于“技术上可行”,能省出 100mb 的显存都要烧高香了。

此外,在 VramOpt 的加持下,远行星号的显存占用没高到离谱的地步,我做到 L4 层的价值是真的很有限。

以上

3l psi 发表于 4 天前

洛赛莱 发表于 2026-10-31 16:08
我是觉得这种涉及游戏引擎层面的东西,最终会产生某种基本的工作方法,变成通用标准。
就像现在的mikohime ...

主要问题是,SS从加载到生涯性能表现,到处都是灾难

一个大而全,全面优化的 mod,性能优化效果好,玩家仅需下载一个就解决问题,这固然是好的,但是开发者这一块,我认为不一定是个好选择:

这对开发者的精力要求,我认为无疑会非常高,要全面处理 SS 的各个领域,项目维护起来我认为会很费劲。

3l psi 发表于 3 天前

3l psi 发表于 2026-11-1 22:30
已实现基于纹理懒加载的显存占用砍半起步

也许会有人问:啊,孢子哥, VramOpt 不已经爆砍显存占用了么


大话说早了,上早八抽空一看工作流,woc,给我气笑了(

此实现距离落地尚有距离,而且这段距离没有想的那么短

3l psi 发表于 3 天前

不要氪命进行 mod 开发,巨大的热情驱动着我,但也要让我这几天快熬成张雪峰了(

晒一下仓库,虽然目前是私有的2333



3l psi 发表于 3 天前

3l psi 发表于 2026-11-1 22:30
已实现基于纹理懒加载的显存占用砍半起步

也许会有人问:啊,孢子哥, VramOpt 不已经爆砍显存占用了么


对不起,做不到(瘫

就目前的实现而言,我认为显存砍不到那个地步。让显存占用可以x0.5~0.7(可以叠加vramopt),是目前理论可行的(还没有经历长时间的生涯测试,也缺乏充分,已记录的数据),至于更激进的卸载策略,先撂一撂

理论上我这些全做完,剩下是漫长的测试,测试,测试。

好消息,预计本周内发布,快的话两三天内。

3l psi 发表于 3 天前

本帖最后由 3l psi 于 2026-11-2 17:12 编辑

3l psi 发表于 2026-11-2 13:54
对不起,做不到(瘫

就目前的实现而言,我认为显存砍不到那个地步。让显存占用可以x0.5~0.7(可以叠加vr ...
谁说我做不到的,孩子们,不过是被 Python 折磨的心灰意冷了(?

下一话!纹理强制 LRU 淘汰!这也就是我在一开始说的,“非常狂野的优化思路”

然后,然后真做不动了...{:5_124:}

这也不是我一开始说的优化思路,那部分狂野的对应我上面帖子提到的 L4 层


MgTi2Nb 发表于 3 天前

等试吃,被多mod折磨好久了,一个存档700mb加载时间上天

3l psi 发表于 3 天前

MgTi2Nb 发表于 2026-11-2 16:19
等试吃,被多mod折磨好久了,一个存档700mb加载时间上天

包子哥手把手教你,如何让你的远行星号加载速度起飞
https://www.fossic.org/thread-21835-1-1.html
(出处: 远行星号中文论坛)

建议先参考此帖子进行优化哦,从打开游戏,到进入主菜单的加载速度,战斗时帧数会得到飞跃改善

此外,我得泼盆冷水,对于存档加载速度,我分享的帖子中提到的手段,和我正在做的此mod,理论上都未对其进行优化(就算有,我也没拉表对比)

3l psi 发表于 3 天前

3l psi 发表于 2026-11-2 15:55
下一话!纹理强制 LRU 淘汰!

然后,然后真做不动了...


已验证其技术可行,实际能用,但是节省的显存过于有限(几十~一两百mb量级)

目前我计划将其仅作为实验性功能,在正式发布时默认关。

3l psi 发表于 3 天前

正在进行收尾工作,包括但不限于兼容性审计等。

饿啊,累死我了——

但是呢,帖子的预期目标,到时候打折扣几乎是必然的,真没啥优化空间了(瘫

GerBeria 发表于 前天 00:10

3l psi 发表于 2026-11-2 23:33
正在进行收尾工作,包括但不限于兼容性审计等。

饿啊,累死我了——


换个角度想,懒加载在叠上自动卸载,不就是用硬盘性能和寿命换到不了几个G的内存/显存吗?
存档方面可以用多线程,但用多线程就得改存档结构,改存档结构就得设计转换工具,设计转换工具工作量和维护面就爆炸,不好做。

3l psi 发表于 前天 00:32

本帖最后由 3l psi 于 2026-11-3 00:36 编辑

GerBeria 发表于 2026-11-3 00:10
换个角度想,懒加载在叠上自动卸载,不就是用硬盘性能和寿命换到不了几个G的内存/显存吗?
存档方面可以 ...
emm,我所设想的流式加载(即自动卸载不加载的纹理),并没有你想的那么吃硬盘寿命,远行星号这游戏的体量摆在那,就算激进到只加载窗口里的纹理,其他部分被立刻卸载,对硬盘寿命的影响,我认为也实在微乎其微。(当然,此猜测缺乏实际数据支撑,考虑到开发成本,似乎也无从验证)

主要问题在于,其工作量是灾难性的,维护成本更是灾难性的,理论上我需要造一个工作量巨大的lib,把远行星号翻个底朝天,设法拦截一切纹理相关的行为(这样才知道全量的哪张纹理什么时候被用了,是否正在用等信息),而且可能游戏本体/任意某个mod,一有变化我就得重新适配。

因此我放弃 L4 层的开发,只把卡在 L1~L2 层之间的一点点实现了,仅作为一个默认关闭(而且无实际价值,能省几十mb显存,这几十mb还是理论值,很容易淹没在数据的噪声里)的实验性功能。理论上全做出来的显存占用优化确实诱人,但开发成本高到不切实际。

3l psi 发表于 前天 16:39

本帖最后由 3l psi 于 2026-11-3 17:36 编辑

兼容性审计,目前来看工作量也不小。


预期最终目标(优化游戏性能的预期 mod 基座):汉化测试版(部分功能实现可能会被短路,以实现兼容,但一定保留高清矢量字体,且性能表现更好,若有短路部分,我会提供一键脚本) + Hypernova + Mikohime 且使用 java 17 以上的大多 java(不确定,可能视 mod 兼容性提供基于不同 java,即 jre17 vs jre17+ 的两版教程) + Fast Rendering( MixinFR? FR +中文输入补丁?同上,看mod兼容性情况)+ VramOpt + StarsectorParallel +StarsectorPrepatcher 。

届时我会写一版(emm,两版?)新的教程,此项目仓库(f25h-233/Hypernova-Infinite-Engine,目前为私有)也会开源。

3l psi 发表于 前天 16:41

此外,此 mod 的开发过程中,还产出了不少可以通用的诊断,调试用脚本/工具等,对于 modder 们来说会很好用,我到时候也整理,打包发个帖子。

3l psi 发表于 前天 18:20

啊啊,漫长的冒烟...

好在这部分算是为数不多的纯体力活(一遍遍的开关mod,启动游戏),我外包给 Claude code了。

所以对于收尾阶段,我的开发经验十分宝贵:

塔露拉三技能也太强了,配个异格拉普兰德加冻河三技能,无限全图打击(doge)

3l psi 发表于 前天 19:03

打开远程桌面一看天塌了,工作流全面爆炸,原因竟是好厚米拿我的套餐狠狠蹬 kimi k3.1 等 sota,给我套餐烧干了...

现在他是坏厚米了()

还在冒烟测试中,我已气冒烟()
页: [1] 2
查看完整版本: [预热&讨论]雷霆优化mod:超新星爆炸:无限引擎