介绍
Jasione
概述
Jasione 是一款优化模组,可减少内存分配(降低 GC 压力)。
Java 编译器会为每个枚举类生成一个 values() 方法,用于以数组形式获取所有枚举值。该方法会在返回数组前先克隆它,确保调用者可以安全地修改数组,而不会影响其他调用者。不过,这会带来性能开销。在频繁调用的代码路径中,这些小额内存分配会不断累积,增加 GC 压力。
Jasione 通过将那些不会修改返回数组的 values() 调用重定向为使用缓存,解决了这一问题,从而消除克隆开销和内存分配。有关如何安全实现这一点的详情,请参阅下文的“技术细节”部分。
配置
Jasione 目前提供了若干调试选项,可用于检查优化结果。配置文件位于 config/jasione.toml。
#指定是否启用该模组
enabled = true
[debug]
#启用后,在应用优化时记录统计信息
printOptimization = false
#启用后,将转换后的类导出到 ".jasione.out" 文件夹
dumpClasses = false
常见问题
JIT 不会优化那些安全的 Enum#values() 调用吗?
不会。目前 JIT 编译器甚至无法识别像遍历 values 数组这样最简单的用法模式。根据 JMH 测试,克隆和内存分配的开销依然存在。
NeoForge 显示了关于此模组的警告。这是为什么?
在最新版本的 NeoForge(1.21.11+)上运行此模组时,可能会遇到以下警告:
[Render thread/ERROR] [ne.ne.fm.cl.tr.ClassTransformStatistics/]: Class processor jasione:main transformed 100.00% of loaded class which is suspiciously high; it may be attempting mass-ASM. Please report this to the mod author.
据 NeoForge 团队成员介绍,这条消息主要是提醒模组作者确认此用例是否确有必要。对于 Jasione 来说,这种转换是必要的。(请参阅上一个问题)
可参考 “The NeoForged Project” Discord 服务器上的讨论(请注意,该讨论涉及不同的实现方案,由于各种问题,这些方案并未成为最终版本。详情请参阅“技术细节”部分。)
技术细节
Enum#values 的约定(此处的 Enum 指任意枚举类)是每次都返回一个全新数组,并且该数组可以自由修改。因此,我们必须通过分析数组是否会被修改或逸出,来识别哪些调用者可以安全地进行优化。这可以通过使用 asm-analysis 库实现。如果字节码分析检测到数组被修改或逸出,则该调用会保持不变,以确保正确性。
我们需要找到一个位置来存储缓存的值数组,因为枚举类的合成 $VALUES 字段是私有的。当前实现会在运行时生成类。针对每个枚举类,都会生成一个对应的缓存持有类,用于通过 static final 字段存储值数组。例如,当转换器首次检测到 net.minecraft.core.Direction#values 被调用时,它会生成类 me.decce.jasione.cached.net.minecraft.core.Direction,其中保存了缓存的值数组以及其他各种元数据,以确保正确性。这样一来,它就能将原始 values() 方法的所有调用方转换为使用缓存类。
常见问题
Jasione 支持哪些 Minecraft 版本?
Jasione 支持 Minecraft Java 版 1.18.2–26.3,共 30 个版本,可用的加载器:Fabric / Forge / NeoForge / Quilt。下载时注意选择和你游戏版本一致的文件。
Jasione 怎么安装?
先用 PCL2 或 HMCL 启动器安装对应版本的 Fabric / Forge / NeoForge / Quilt,再把下载的 .jar 文件放进游戏目录的 mods 文件夹,重新启动游戏即可。开启了版本隔离的,mods 文件夹在 versions/版本名 下面。
评论
登录后评论和评分