-
Notifications
You must be signed in to change notification settings - Fork 38.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Regression: Slow TypeDescriptor lookups in CachedIntrospectionResults on IBM JVM 6 [SPR-12185] #16799
Comments
Juergen Hoeller commented I'm switching that type descriptor cache to our own This will be available in the upcoming 4.1.1 snapshot. If this does not sufficiently address your performance regression, we'll have to consider introducing a property that controls the use of the cache to begin with, as you suggested. Juergen |
Torsten Hartwig commented Further information: IBM's implementation of PropertyDescriptor (in beans.jar) is buggy in JVM 1.6; for several PropertyDescriptors pd.quals(pd) returns false. java.util.HashMap works fine in most cases as it does (localObject = localEntry.key) == paramObject) || ((paramObject != null) && (paramObject.equals(localObject)) while ConcurrentHashMap does not compare both objects but relies on "equals" only. The problem is probably fixed in JVM 1.7 as PropertyDescriptor.equals(..) (in rt.jar) does a direct comparison if (this == paramObject) { which was not present in JVM 1.6. |
Juergen Hoeller commented Thanks for the detailed analysis, Torsten... I'll double-check that we're explicitly comparing instance identity for PropertyDescriptors wherever we can. Juergen |
Jörg Fraune commented Update: Actually the cached objects are org.springframework.beans.GenericTypeAwarePropertyDescriptor; this class does not implement it's own equals-method but relies on java.beans.PropertyDescriptor. The IBM-Implementation does
with getter being a member variable holding the readMethod. GenericTypeAwarePropertyDescriptor overloads getReadMethod and has it's own private member variable "readMethod". This way the equals method fails if readMethod (or writeMethod, which is handled the same way) is not null. Probably GenericTypeAwarePropertyDescriptor should define it's own equals-method. |
Jörg Fraune commented Probably fix for GenericTypeAwarePropertyDescriptor neccessary |
Juergen Hoeller commented Good point, looks like That said, with Juergen |
Juergen Hoeller commented The Juergen |
Juergen Hoeller commented This is available in the latest 4.1.1 and 4.0.8 snapshots now. It would be great if you could give both a try since the implementation unfortunately has to differ in the details due to specific arrangements in each branch. Juergen |
Jörg Fraune commented 4.0.8-snapshots are not yet available (newest file at http://maven.springframework.org/snapshot/ is spring-beans-4.0.8.BUILD-20140904.082040-1.jar); tests with 4.1.1 (spring-beans-4.1.1.BUILD-20140917.003734-10.jar) were as fast as our builds with caching disabled (that's great). Will test 4.0.8-snapshots as they become available, will retest 4.1.1-snapshots as they probably did not yet contain your latest fix (though I think they will not become slow again). Thanks, Jörg |
Juergen Hoeller commented Oops, the CI build kept failing there because of some rather fragile multi-threading tests. The latest 4.0.x build has passed - a new 4.0.8 snapshot should be available now. Thanks for the quick turnaround! Juergen |
Jörg Fraune commented Tested 4.0.8-snapshot now, works like a charm (same performance as 4.1.1-snapshot). Will switch to 4.1.1 when it is released. Thank you, Jörg |
Juergen Hoeller commented That's great to hear! 4.1.1 is due on Sep 30 - in less than two weeks. Juergen |
Craig commented Is this actually a bug in IBM Java's implementation of java.beans.PropertyDescriptor? Has this issue been reported to IBM? |
Jörg Fraune commented I don't think so; the implementation of java.beans.PropertyDescriptor (or it's equals-method) looks a little bit clumsy but not wrong. So does the implementation of ConcurrentHashMap in IBMs JDK 1.6, but at least this has been optimized in JDK 1.7. Jörg |
Craig commented FYI, I reported this issue to IBM, service request number 06478,024,649.
|
Jörg Fraune commented I tested this with different IBM JDKs:
|
Craig commented IBM has confirmed and fixed the problem:
They also confirmed that this issue only impact Java 6 - IBM Java 7 is not affected. |
Torsten Hartwig opened SPR-12185 and commented
We upgraded our portal web application from Spring 2.5.6 to 4.0.6 and got into trouble with a very high load, when many users access the frontend.
Every request performs slower with a factor 2 and more with the new Spring version. We tried to reproduce it with Spring 3.2.9, but the load was the same like 2.5.6.
Our application is configured with a parent ear-context to share singletons and every war in that ear has its own web-context. Furthermore every portlet has its own small portlet-app-context. The number of all defined beans is about 1500, 300 are request-scoped.
We investigated that method BeanWrapperImpl.convertForProperty works slow and figured out that behavior of this method has changed from 2.5.6/3.2.9 to 4.X. In 2.5.6/3.2.9 every time BeanWrapperImpl.convertForProperty is called,
a new instance of TypeDescriptor is created. In 4.X every time BeanWrapperImpl.convertForProperty is called, first cachedIntrospectionResults.getTypeDescriptor(pd) is called and if it is null,
cachedIntrospectionResults.addTypeDescriptor is called. And in our case both cache-lookups are much slower than creating a new instance. With a local interim-fix which disabled the cache-lookups in 4.0.6 we could establish
the same performance like 2.5.6/3.2.9 .
Even introducing an optimized cach-lookup
TypeDescriptor addTypeDescriptor(PropertyDescriptor pd, TypeDescriptor td) {
TypeDescriptor existing = this.typeDescriptorCache.putIfAbsent(pd, td);
return (existing != null ? existing : td);
}
in CachedIntrospectionResults in Spring 4.1 does not improve the performance.
I don't know the reason for new cache-lookup behavior in CachedIntrospectionResults and the dimension of number of beans that must be declared to become slower with cache-lookups than with creating new instances of TypeDescriptor.
But can you introduce a new spring property that disables the cache lookups and restore "old" behavior? You did something similar with property spring.beaninfo.ignore to skip lookup of BeanInfo classes.
Update (20140912):
Further investgations led to the result that the ConcurrentHashMap-Implementation in our JVM (IBM/WAS 7.0.0.21) may be broken as the get method always returned null, even if the element was inserted just before.
Experimentally replacing ConcurrentHashMap by Collections.synchronizedMap(new HashMap()) seems to resolve this issue. Due to the fact that synchronizedMap uses locking (and can block) we would not use this in our productive environment.
Affects: 4.0.7, 4.1 GA
Referenced from: commits b39e66b, 5cd59d0, d1c720c, c52484e
Backported to: 4.0.8
1 votes, 6 watchers
The text was updated successfully, but these errors were encountered: