Spring Bean Factory creation of Prototype (non-singleton) beans causes serious 
performance degradation under load
-----------------------------------------------------------------------------------------------------------------

                 Key: JS2-689
                 URL: https://issues.apache.org/jira/browse/JS2-689
             Project: Jetspeed 2
          Issue Type: Bug
          Components: Components Core
    Affects Versions: 2.2-dev
            Reporter: David Sean Taylor
         Assigned To: David Sean Taylor
             Fix For: 2.2-dev


It appears that Spring prototype (non-singleton) bean factory creations cause 
synchronization contention issues under load.
The NavigationalState and PortalURL beans are created several times per request.
Under load with JMeter tests, the synchronization of Java Bean support code (in 
the JDK), called by Spring's bean factory, was causing severe performance 
degradation.
Removing this bottleneck improved performance by 5X.
I've attached the Java source from the package java.beans. I believe its these 
synchronized methods of the java.beans.PropertyEditorManager class that are 
causing the contention:

private static synchronized void initialize() {
private static synchronized void load(Class targetType, String name) {


See attached screenshot for performance results before and after removal of 
prototypes (replaced by constructors). 
Using a 4 processor CPU really brings the contention issue to the forefront.

When we have hundreds of requests active, there are over 90 blocked threads in 
the findEditor stack frame:

Thread [EMAIL PROTECTED]: (state = BLOCKED)
- java.beans.PropertyEditorManager.findEditor(java.lang.Class) @bci=0, line=75 
(Compiled frame; information may be imprecise)
- 
org.springframework.beans.TypeConverterDelegate.convertIfNecessary(java.lang.String,
 java.lang.Object, java.lang.Object, java.lang.Class, 
java.beans.PropertyDescriptor, org.springframework.core.MethodParameter) 
@bci=115, line=174 (Compiled frame)
- 
org.springframework.beans.TypeConverterDelegate.convertIfNecessary(java.lang.Object,
 java.lang.Class, org.springframework.core.MethodParameter) @bci=7, line=95 
(Compiled frame)
- 
org.springframework.beans.factory.support.AbstractBeanFactory.doTypeConversionIfNecessary(org.springframework.beans.TypeConverter,
 java.lang.Object, java.lang.Class, org.springframework.core.MethodParameter) 
@bci=47, line=761 (Compiled frame)
- 
org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(java.lang.String,
 org.springframework.beans.factory.support.RootBeanDefinition) @bci=191, 
line=126 (Compiled frame)
- 
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(java.lang.String,
 org.springframework.beans.factory.support.RootBeanDefinition) @bci=12, 
line=683 (Compiled frame)
- 
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(java.lang.String,
 org.springframework.beans.factory.support.RootBeanDefinition, 
java.lang.Object[]) @bci=224, line=380 (Compiled frame)
- 
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(java.lang.String,
 java.lang.Class, java.lang.Object[]) @bci=362, line=264 (Compiled frame)
- 
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(java.lang.String,
 java.lang.Class) @bci=4, line=160 (Compiled frame)
- 
org.apache.jetspeed.container.state.impl.JetspeedNavigationalStateComponent.createURL(javax.servlet.http.HttpServletRequest,
 java.lang.String) @bci=29, line=131 (Compiled frame)
- org.apache.jetspeed.pipeline.JetspeedPipeline$Invocation.invokeNex

My first solution was to remove the Spring prototype code and replace it with 
straight constructors (replacing commented code below):

    public PortalURL createURL( HttpServletRequest request, String 
characterEncoding )
    {
        //PortalURL url = (PortalURL) beanFactory.getBean(urlBeanName, 
PortalURL.class);  <--- **** used to be one line prototype creation, commented 
out....
        NavigationalStateCodec codec = 
(NavigationalStateCodec)beanFactory.getBean("NavigationalStateCodec");
        JetspeedCache cache = 
(JetspeedCache)beanFactory.getBean("portletContentCache");
        NavigationalState navState = new SessionFullNavigationalState( codec, 
cache);
        PortalContext context = 
(PortalContext)beanFactory.getBean("PortalContext");
        PortalURL url = new PathInfoEncodingPortalURL(navState, context);

Perhaps it could be configured as:

    public PortalURL createURL( HttpServletRequest request, String 
characterEncoding )
    {
        if (useSpringToWireBeans)
        {
                PortalURL url = (PortalURL) beanFactory.getBean(urlBeanName, 
PortalURL.class);
        }
        else
        {
              NavigationalStateCodec codec = 
(NavigationalStateCodec)beanFactory.getBean("NavigationalStateCodec");
              JetspeedCache cache = 
(JetspeedCache)beanFactory.getBean("portletContentCache");
              NavigationalState navState = new SessionFullNavigationalState( 
codec, cache);
              PortalContext context = 
(PortalContext)beanFactory.getBean("PortalContext");
              PortalURL url = new PathInfoEncodingPortalURL(navState, context);

I will also create an issue in Spring JIRA and see if we can get resolution 
from the Spring team.....


-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to