通过字节码分析安全消除 Enum#values 数组克隆和内存分配开销,从而降低 GC 压力。
Jasione 概述 Jasione 是一个优化模组,用于减少内存分配(降低 GC 压力)。 Java 编译器会为每个枚举类生成一个 values() 方法,该方法可用于将所有枚举值检索为数组。此方法在返回数组之前会对其进行克隆,确保调用此方法的调用者可以安全地修改数组,而不会影响其他调用者。然而,这会产生性能开销。当在热点路径中调用时,这些微小的内存分配会累积并增加 GC 压力。 Jasione 通过重定向那些不修改返回数组的 values() 调用以使用缓存来解决此问题,从而消除克隆开销和内存分配。有关如何安全实现此功能的详细信息,请参阅下方的“技术细节”部分。 配置 Jasione 目前提供几种调试选项,可用于检查优化结果。配置位于 config/jasione.toml . #Specifies whether to enable the mod enabled = true [debug] #When enabled, logs statistics when optimizations are applied printOptimization = false #When enabled, dumps transformed classes to the ".jasione.out" folder dumpClasses = false 常见问题解答 JIT 不会在安全的情况下优化 Enum#values() 调用吗? 不会,JIT 编译器目前甚至无法识别最简单的使用模式,例如遍历值数组。克隆和内存分配的开销仍然存在,详见 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,这种转换是必要的。(参见上一个问题) 参考,请参见 关于“NeoForged Project”Discord 服务器上的讨论 (请注意,该讨论涉及不同的实现,由于各种问题,这些实现并未成为最终版本。更多详情请参阅“技术细节”部分。) 技术细节 The contract of Enum#values (其中 Enum 指代任何枚举类)的契约规定,返回的数组是新的且可以自由修改。因此,我们必须通过分析调用者是否修改数组或数组是否逃逸来识别哪些调用者是可安全优化的。利用 asm-analysis 库使得这一过程成为可能。如果通过字节码分析检测到数组修改或逃逸,则调用保持不变以保持正确性。 我们需要找到一个地方来存储缓存的值数组,因为枚举类的合成 $VALUES 字段是私有的。当前实现执行运行时类生成。对于每个枚举类,都会生成一个相应的缓存持有者类,将值数组存储为 static final 字段。例如,当转换器首次检测到对 net.minecraft.core.Direction#values 的使用时,它会生成类 me.decce.jasione.cached.net.minecraft.core.Direction , 该类包含缓存的值数组以及确保正确性的各种其他元数据。通过这种方式,它可以将原始 values() 方法的所有调用者转换为使用缓存类。
在鱼乐云资源中心浏览该资源,登录后可一键安装到你的游戏服务器。