Results 1 to 7 of 7

Thread: Performance issue while instantiating prototype beans

Threaded View

  1. #1
    Join Date
    Jan 2012
    Posts
    5

    Unhappy Performance issue while instantiating numerous prototype beans

    Hi,

    Sorry, I am new to spring and new to this forum. Feel free to criticize anything.

    I am using spring 3.0.5.

    My overall issue is that I need to instantiate numerous (Let's say dozens or hundreds of thousands) prototype beans from several singleton beans. I don't know the instantiation count at application startup. The application need to be very fast (But should rely on spring).

    In the following code, the singleton bean "Foo" need to create "count" of "MyBean" when its "perform" method is called.
    Three different ways are used to create the "MyBean" instances.
    1/ Using beanFactory.getBean(String). "FooImpl" implements BeanFactoryAware so it can use it to retrieve an instance by name.
    2/ Using beanFactory.getBean(Class). Instead of using the bean name, the class is used.
    3/ Using myBeanFactory.getObject(). An ObjectFactory<MyBean> is injected using @Autowired. So it is used to create instances.

    Code:
    @Configuration
    public class MyConfiguration
    {
    	@Bean
    	public Foo foo()
    	{
    		return new FooImpl();
    	}
    
    	@Bean
    	@Scope("prototype")
    	public MyBean myBean()
    	{
    		return new MyBeanImpl();
    	}
    }
    
    public class FooImpl implements Foo, BeanFactoryAware
    {
    	@Autowired
    	private ObjectFactory<MyBean> myBeanFactory;
    
    	private BeanFactory beanFactory;
    
    	public void perform(int count)
    	{
    		SimpleChrono chrono1 = new SimpleChrono("BeanFactory, by name");
    		for (int i = 0; i < count; i++)
    		{
    			MyBean myBean = (MyBean)beanFactory.getBean("myBean");
    		}
    		chrono1.stop();
    
    		SimpleChrono chrono2 = new SimpleChrono("BeanFactory, by class");
    		for (int i = 0; i < count; i++)
    		{
    			MyBean myBean = (MyBean)beanFactory.getBean(MyBean.class);
    		}
    		chrono2.stop();
    
    		SimpleChrono chrono3 = new SimpleChrono("ObjectFactory");
    		for (int i = 0; i < count; i++)
    		{
    			MyBean myBean = myBeanFactory.getObject();
    		}
    		chrono3.stop();
    	}
    
    	@Override
    	public void setBeanFactory(BeanFactory beanFactory) throws BeansException
    	{
    		this.beanFactory = beanFactory;
    	}
    }
    It is written in several places on the web that getBean(String) is not supposed to be very fast. It is even in the old javadoc.
    Note that callers should retain references to returned objects. There is no guarantee that this method will be implemented to be efficient. For example, it may be synchronized, or may need to run an RDBMS query.
    I thought it would be a difficult task for getBean(String) to find the corresponding class to instantiate basing on the configuration field name.
    I thought that getBean(Class) would be faster.
    And I thought that the dedicated factory would be far more faster. Because it is dedicated. The needed class is known at compilation time, the factory has to provide instances of a single class... The first getObject() could be slow, but others would be damn fast.

    I was all wrong. Here are the results (For count = 10000):

    12/01/12 18:06:47 DEBUG Starting 'BeanFactory, by name'.
    12/01/12 18:06:48 DEBUG End of 'BeanFactory, by name' 00:00:01:125
    12/01/12 18:06:48 DEBUG Starting 'BeanFactory, by class'.
    12/01/12 18:07:08 DEBUG End of 'BeanFactory, by class' 00:00:20:187
    12/01/12 18:07:08 DEBUG Starting 'ObjectFactory'.
    12/01/12 18:07:29 DEBUG End of 'ObjectFactory' 00:00:20:516
    getBean(String) is twelve times faster than others methods...
    Why the hell?

    Here is profiler screenshot for getObject.

    The method 3 with a dedicated factory seems really cleaner to me. But due to performance issue, I will have do use getbean(String)?

    MyBean could be a classical java class, not used as a bean with spring dependency injection. So I would have to manually give to MyBean its dependency. What are the others drawbacks with this solution ?

    Is there others ways to solve this problem?
    Last edited by rt15; Jan 23rd, 2012 at 08:24 AM.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •