sve*_*eri 6 java reflection performance osgi
我们有一个OSGi容器,里面有很多产品,其中一个是我们的产品.
我们正在运行一些性能测试,并且存在一个奇怪的问题,即每个OSGi容器重启都会导致我们的一些测试的性能偏差高达400%.
通过一些测试和事情,我能够跟踪这个方法:
public static Method getMethodForSlotKey(Class<?> cls, String slotKey, String methodType) {
Method[] methods = cls.getMethods();
if (methods != null && methods.length > 0) {
for (Method method : methods) {
String methName = method.getName();
if (methName.startsWith(methodType)) {
IDataAnnotation annot = method.getAnnotation(IDataAnnotation.class);
if (annot != null) {
String annotSlotKey = annot.SlotKey();
if (annotSlotKey != null && annotSlotKey.equals(slotKey)) {
Class<?>[] paramTypes = method.getParameterTypes();
// for now, check length == 1 for setter and 0 for getter.
int len = SET_TXT.equals(methodType) ? 1 : 0;
if (paramTypes != null && paramTypes.length == len) {
return method;
}
}
}
}
}
}
return null;
}
Run Code Online (Sandbox Code Playgroud)
该方法主要进行反射和字符串比较.
现在,我所做的是缓存此方法的结果,立即我们的偏差降至10 - 20%.当然,这种方法经常被调用,因此有很明显的改进.
我仍然不明白为什么非缓存版本有这么高的偏差,唯一的区别是OSGi/JVM重启?重启期间究竟会发生什么?例如,对于不同的类加载器是否存在任何已知的性能问题?是否有可能在OSGi环境中,库将在重新启动之间以不同的顺序加载?
我在这里寻找一条线索,这是有道理的.
UPDATE
原来这个电话:
Method[] methods = cls.getMethods();
Run Code Online (Sandbox Code Playgroud)
导致偏差.我仍然不明白,所以如果有人这么做,我会很高兴听到它.
我怀疑这是因为您重新启动服务器/OSGi 容器正在清除Method[]
您正在询问的类中的缓存*。缓存将被清除,以确保在重新加载的类具有与同名的旧类不同的公共 API(即不同的方法)的情况下正确操作(例如,如果您加载较新的版本,则可能会发生这种情况)
当您实现“包装器”方法的缓存时,您就规避了这一点并引入了一个假设 - 重新加载的类将具有与先前加载的同名类相同的方法。对于大多数情况来说,这可能是一个相当安全的假设,但不是您希望核心 Java 做出的假设。
Class
(OpenJDK)类的源代码在这里。如果你仔细查看它,你会发现getMethods()
调用privateGetPublicMethods()
. 如果缓存的publicMethods
array* 为 null,或者由 设为 null clearCachesOnClassRedfinition()
,则该类将必须经历相对密集的过程,查找该类中的所有公共方法以及它继承的任何超类和它实现的接口。然后将其缓存,速度getMethods()
将恢复正常。
*严格来说,缓存的值是对数组的软引用。
归档时间: |
|
查看次数: |
277 次 |
最近记录: |