介绍
项目已废弃
长话短说,这种优化方案依然有效,但 Forge/NeoForge 不允许模组修改 EventBus。
与 Minecraft 或 Forge 本身中的类不同,EventBus 并不是作为游戏的一部分加载的,而是作为“library”加载的,因此无法通过 Mixin 或 Transformer 修改 EventBus。
在 1.2.0 版本中,为了进一步提升性能,我使用了一些不太常规的技巧(如果你愿意,也可以称之为“非标准方案”)来修改 ASMEventHandler 类,但遗憾的是,该方案在 1.18.2 及更高版本中已失效。这些版本现已归档,之后可能也不会再获得更新。
FastEvent
是一个 Forge/Neoforge 优化模组,用于优化 Forge 中最基础的系统之一:事件系统。
性能如何
要为每个受支持的 Minecraft 版本制作测试用例并不容易,尤其是这些版本的事件系统彼此并不相同。因此,我将提供一份来自我为 Cleanroom 项目提交的 PR 的 JMH 基准测试报告,其中使用了与 FastEvent 相同的优化方案:
注册 10,000 个事件监听器,不发布事件:
Benchmark Mode Cnt Score Error Units
BusPerformanceTest.register10000Legacy avgt 5 1126.498 ± 284.633 ms/op
BusPerformanceTest.register10000Modern avgt 5 1058.961 ± 173.586 ms/op
速度提升约 6.4%。
注册 1,000 个事件监听器,发布事件 10,000 次:
Benchmark Mode Cnt Score Error Units
BusPerformanceTest.register1000test10000Legacy avgt 5 4407.963 ± 4250.643 ms/op
BusPerformanceTest.register1000test10000Modern avgt 5 3550.578 ± 1991.352 ms/op
速度提升约 24%。
原始 PR
https://github.com/CleanroomMC/Cleanroom/pull/328#issuecomment-2801099504
它是如何工作的
(技术细节警告)
当开发者使用 @EventBusSubscriber 和/或 @SubscribeEvent 订阅事件处理器时,EventBus 无法凭空获取事件处理器,而只能获得一个 Method 对象。因此,最直接的做法就是直接使用这个对象:method.invoke(...)。这个调用最终会被 JVM 重定向回原始方法,使事件处理器在订阅事件后能够接收到事件。
但这种方式(method.invoke(...))的速度非常慢。为了提升速度,EventBus 会在运行时为它找到的每个方法生成事件处理器类,从而避免开销高昂的基于反射的调用。
不过,生成类本身也会带来额外的性能损耗。为了进一步提升速度,FastEvent 使用 lambda 构造替代了类生成,从而加快了事件处理器的构建速度。此外,lambda 还是“隐藏的”,这使 JVM 能够进行更多优化。
如果你对 Java 有一定了解,下面的代码示例可能会更直观:
class Listen {
public void onEvent(Event event) {
}
}
Listen lis = new Listen();
// EventBus will generate a new class for every event handler
class IEventListener$Listen$onEvent implements IEventListener {
private Listen instance;
public IEventListener$Listen$onEvent(Listen instance) {
this.instance = instance;
}
@Override
public void invoke(Event event) {
instance.onEvent(event);
}
}
IEventListener handler = new IEventListener$Listen$onEvent(lis);
// FastEvent uses lambda to generate event handler
IEventListener handler = lis::onEvent;
常见问题
FastEvent 支持哪些 Minecraft 版本?
FastEvent 支持 Minecraft Java 版 1.16.5–1.21.1,共 5 个版本,可用的加载器:Forge / NeoForge。下载时注意选择和你游戏版本一致的文件。
FastEvent 怎么安装?
先用 PCL2 或 HMCL 启动器安装对应版本的 Forge / NeoForge,再把下载的 .jar 文件放进游戏目录的 mods 文件夹,重新启动游戏即可。开启了版本隔离的,mods 文件夹在 versions/版本名 下面。运行环境:客户端 / 服务端。
ZZZank 的其他作品
查看全部 →
EventJS
Sided reloadable native event for KubeJS
EfficientHashing
better hashing algorithm for Vec3i & BlockPos
JEI Area Fixer
fix JEI GUI to not overlap with modded GUIs
MiniEffects-Legacy Extended Life
fork of MiniEffects for Minecraft 1.12, with more feature(s) like JEI bookmark support
评论
登录后评论和评分