好的稍等我想想PowerNukkitX项目有一个很久没有解决的性能问题,希望大佬能帮忙指点一二:
PNX服务端中具有一个事件派发系统,一旦某个事件发生,就会将注册了的监听器对象中的特定方法一一调用,但是调用事件监听器的开销相对于直接内联方法调用而言大不少,所以我们十分迫切地希望能够对它进行优化,请问您有相关思路吗?
最开始,我们通过反射获取方法对象并通过反射invoke调用用哈希表注册的监听器,但是反射的开销是直接内联调用的几十倍。后来开发组编写了一个内嵌的专用编译器,将事件系统中所有的反射调用都编译成lambda调用(invokeVirtual或invokeDynamic)然后注入JVM中。目前遇到的性能问题就在这里:小部分编码不良的插件频繁地注册和取消监听器类,这导致我们需要频繁地对AppClassLoader中的类表进行注册和取消,而这个过程中由于JVM的类保存机制,很多完全没用的类会挤压在堆上的元空间中,导致内存浪费;而且,加载一个新的lambda时,我们即便确认生成的字节码没有问题,JVM仍然会进行开销高昂的类验证,这也导致了开服速度有一定下降。有什么好的方法来避免这一点呢?感谢
好的您好 我认为您可以去帮助Geyser成员完成他们的工作 让他们的翻译移动变的香草化 他们还尚未解决 互通服的希望就交给您了 您去帮助Geyser解决问题吧!
GeyserGithub: https://github.com/GeyserMC/Geyser
好的,我现在正在编写一个基础监听器,灵敏性高,内存较多,开销较少PowerNukkitX项目有一个很久没有解决的性能问题,希望大佬能帮忙指点一二:
PNX服务端中具有一个事件派发系统,一旦某个事件发生,就会将注册了的监听器对象中的特定方法一一调用,但是调用事件监听器的开销相对于直接内联方法调用而言大不少,所以我们十分迫切地希望能够对它进行优化,请问您有相关思路吗?
最开始,我们通过反射获取方法对象并通过反射invoke调用用哈希表注册的监听器,但是反射的开销是直接内联调用的几十倍。后来开发组编写了一个内嵌的专用编译器,将事件系统中所有的反射调用都编译成lambda调用(invokeVirtual或invokeDynamic)然后注入JVM中。目前遇到的性能问题就在这里:小部分编码不良的插件频繁地注册和取消监听器类,这导致我们需要频繁地对AppClassLoader中的类表进行注册和取消,而这个过程中由于JVM的类保存机制,很多完全没用的类会挤压在堆上的元空间中,导致内存浪费;而且,加载一个新的lambda时,我们即便确认生成的字节码没有问题,JVM仍然会进行开销高昂的类验证,这也导致了开服速度有一定下降。有什么好的方法来避免这
开发前端原代码:PowerNukkitX项目有一个很久没有解决的性能问题,希望大佬能帮忙指点一二:
PNX服务端中具有一个事件派发系统,一旦某个事件发生,就会将注册了的监听器对象中的特定方法一一调用,但是调用事件监听器的开销相对于直接内联方法调用而言大不少,所以我们十分迫切地希望能够对它进行优化,请问您有相关思路吗?
最开始,我们通过反射获取方法对象并通过反射invoke调用用哈希表注册的监听器,但是反射的开销是直接内联调用的几十倍。后来开发组编写了一个内嵌的专用编译器,将事件系统中所有的反射调用都编译成lambda调用(invokeVirtual或invokeDynamic)然后注入JVM中。目前遇到的性能问题就在这里:小部分编码不良的插件频繁地注册和取消监听器类,这导致我们需要频繁地对AppClassLoader中的类表进行注册和取消,而这个过程中由于JVM的类保存机制,很多完全没用的类会挤压在堆上的元空间中,导致内存浪费;而且,加载一个新的lambda时,我们即便确认生成的字节码没有问题,JVM仍然会进行开销高昂的类验证,这也导致了开服速度有一定下降。有什么好的方法来避免这一点呢?感谢
但我无法看出这跟我的问题有什么关系。开发前端原代码:
package org.apollodevs.helloworld.commands;
import org.apollodevs.helloworld.Main;
public class helloComand implements CommandExecutor{
Suppres sWarnings("unused")
private main plugin;
public helloCommand(Main plugin) {
this.plugin - plugin;
plugin.getCommand("hello").setExecutor(this);
}
player p - (player) sender;
if (p.hasPermission("hello.use)) {
p.sendMessage("hil");
return yure;
}else {
p.sendMessage("you do not have permission to execute thos command!");
}
return false;
}
}
几个问题:开发前端原代码:
package org.apollodevs.helloworld.commands;
import org.apollodevs.helloworld.Main;
public class helloComand implements CommandExecutor{
Suppres sWarnings("unused")
private main plugin;
public helloCommand(Main plugin) {
this.plugin - plugin;
plugin.getCommand("hello").setExecutor(this);
}
player p - (player) sender;
if (p.hasPermission("hello.use)) {
p.sendMessage("hil");
return yure;
}else {
p.sendMessage("you do not have permission to execute thos command!");
}
return false;
}
}
这明显是不知道在哪抄的图片转文字几个问题:
这段代码里的Suppres明显不是java关键字 结合上下文应改为@SuppressWarnings("unused")
return yure; 很显然java里没有个东西叫yure,应该是true 如果你在main里定义了一个叫yure的玩意 当我没说
java是个大小写敏感的语言 你import的是Main为什么下面声明变量类型的时候变成了main 这样类型根本不匹配
player p - (player) sender -应该是=。另一个this.plugin - plugin;同理。
"hello.use这一段会导致你下面的一切全部被当做字符串处理 应该是"hello.use"。
最离谱的:helloCommand这个方法下面的所有调用 不属于任何一个方法 丢进编译器里立马爆炸
提示文本里的一堆错词我就不说了。
这位的其他问题我基本上不会,但是类验证……试试-noverify(雾)