Description
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