Skip to content

Performance Improvement: Enable Lazy Initialization #12500

@rainboyan

Description

@rainboyan

Spring Boot 2.2 M1, Provide a configuration option to enable lazy initialisation

https://spring.io/blog/2019/03/14/lazy-initialization-in-spring-boot-2-2

It’s possible to enable lazy initialization in any version of Spring Boot if you’re happy to get your hands dirty and write a BeanFactoryPostProcessor. Spring Boot 2.2 just makes it easier via the introduction of a new property, spring.main.lazy-initialization (there are also equivalent methods on both SpringApplication and SpringApplicationBuilder). When set to true, bean definitions in the application will be configured to use lazy initialization.

Currently, Grails 5 support lazy initialization like this,

        gspTagLibraryLookup(TagLibraryLookup) { bean ->
            bean.lazyInit = true
        }

In Grails, if not set lazyInit, the BeanDefinition.isLazyInit() will be false default.

We can't config spring.main.lazy-initialization to enable global lazy initialization.

In Spring Boot LazyInitializationBeanFactoryPostProcessor, this PostProcessor will set LazyInit true if getLazyInit() was null, but Grails always set false.

	private void postProcess(ConfigurableListableBeanFactory beanFactory,
			Collection<LazyInitializationExcludeFilter> filters, String beanName,
			AbstractBeanDefinition beanDefinition) {
		Boolean lazyInit = beanDefinition.getLazyInit();
		if (lazyInit != null) {
			return;
		}
		Class<?> beanType = getBeanType(beanFactory, beanName);
		if (!isExcluded(filters, beanName, beanDefinition, beanType)) {
			beanDefinition.setLazyInit(true);
		}
	}

I create a large Grails app which has 2000 Beans, and I configure them in conf/spring/resources.groovy,

then, I test it on my old MacBook,

  • Mac OS 10.14.6, later 2013 8G RAM
  • Grails 5.1.7
  • Java 11.0.14-zulu
Bean & Config resources.groovy lazy-initialization: true lazy-initialization: false
0 + 0 7606ms 6478ms 7146ms
2000 + 0 18614ms 17251ms 17704ms

Also I edit the Grails source code, to enable lazy initialization like Spring Boot 2.2,


    protected AbstractBeanDefinition createBeanDefinition() {
        AbstractBeanDefinition bd = new GenericBeanDefinition();
...
        if(clazz != null) {
             // bd.setLazyInit( clazz.getAnnotation(Lazy.class) != null);
             if (clazz.getAnnotation(Lazy.class) != null) {
                 bd.setLazyInit(true);
             }
             bd.setBeanClass(clazz);
         }
...
        return bd;
    }

the test result was below, it's better than previous version.

Bean & Config resources.groovy lazy-initialization: true lazy-initialization: false
0 + 0 6243ms (18% ↓) 5862ms (23% ↓)
2000 + 0 18885ms 14423ms (24% ↓) 18462ms

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions