Performance deviation for a small method

We have an OSGi container with many products working internally, one of which is our product.
We have some performance tests, and there is this strange problem: every restart of the OSGi container will lead to a performance deviation of up to 400% for some of our tests.
After some testing and stuff, I was able to track this with this method:

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; } 

This method basically does reflection and string comparison.

Now, I did this to cache the results of this method, and instantly our deviation is reduced to 10-20%. Of course, this method is often called, so there is an improvement that is obvious.

However, I don’t understand why the non-cached version has such a high deviation with the only difference being that restarting OSGi / JVM? What exactly can happen during a restart? Are there any known performance issues for different class loaders? Is it possible that in OSGi, libraries will be loaded in a different order between restarts?

I am looking for a key for this to make sense.

UPDATE

It turns out this call:

 Method[] methods = cls.getMethods(); 

causes a deviation. I still do not understand this, so if anyone does this, I will be glad to hear about it.

+6
source share
2 answers

I suspect this is because your reloading of your server / OSGi container clears the cached Method[] * in the class (s) you are requesting. The cache will be cleared to ensure proper operation in a situation where the reloaded class has a different public API (i.e., different methods) than the old one with the same name (this can happen, for example, when loading a newer version)

When you implement your cache of your wrapper method, you bypass this and enter the assumption that the reloaded classes will have the same methods as previously loaded classes with the same name. This is probably a pretty safe assumption for most cases, but not the one you would like to create a Java kernel for.

The source code for the (OpenJDK) Class here . If you look at it, you'll see that getMethods() calls privateGetPublicMethods() . If the cached publicMethods array * is NULL, or its value is null, clearCachesOnClassRedfinition() , then the class will have to go through a relatively intensive process of searching for all public methods in the class and any superclasses that it inherits and the interfaces that it implements. Then it is cached and the speed of getMethods() will return to its normal state.


* strictly, a cached value is a soft reference to an array.

0
source

This seems to be another case of complex JIT, which seems to be constantly changing and evolving over time. This answer may shed light on your problem: Java: what is JITC reflection inflation?

I believe that you are seeing the effects of how JIT optimizes your reflex calls. Some time (the first X calls) will be slow until the JIT decides to optimize your method.

Something you can try - to check this theory - is to change your code and put the disturbing call in a dummy loop and execute it several times at the first call (make sure you did something with the result, call to force java not to completely disconnect the call if it shows that it has no consequences). If this leads to a very long run time for first use, and then to a very low dispersion of subsequent calls, then the theory sounds right.

0
source

Source: https://habr.com/ru/post/980936/


All Articles