Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Speed up Spring Boot startup time

People also ask

How do I reduce startup time on spring boot?

spring.main.lazy-initialization=true Setting this property truely will initialize the bean only after it comes into the picture. This property will reduce the run time of the application. We can see that when the property is not applied, the running time is approximately around 8.4 seconds.

Why does spring boot take so long to start?

When a Spring Boot Application has slow startup, it can be one or more beans and related dependencies taking longer to initialise and slowing down the entire process. Profiling Spring Boot application doesn't often help in diagnosing the startup issues.

Are spring boots faster?

We see from the graphs that it is quite possible to run a simple Netty app in 10MB heap with Spring Boot 2.1 (but not with 2.0). It is also a bit faster in 2.1 compared to 2.0.


Spring Boot does a lot of auto-configuration that may not be needed. So you may want to narrow down only auto-configuration that is needed for your app. To see full list of auto-configuration included, just run logging of org.springframework.boot.autoconfigure in DEBUG mode (logging.level.org.springframework.boot.autoconfigure=DEBUG in application.properties). Another option is to run spring boot application with --debug option: java -jar myproject-0.0.1-SNAPSHOT.jar --debug

There would be something like this in output:

=========================
AUTO-CONFIGURATION REPORT
=========================

Inspect this list and include only autoconfigurations you need:

@Configuration
@Import({
        DispatcherServletAutoConfiguration.class,
        EmbeddedServletContainerAutoConfiguration.class,
        ErrorMvcAutoConfiguration.class,
        HttpEncodingAutoConfiguration.class,
        HttpMessageConvertersAutoConfiguration.class,
        JacksonAutoConfiguration.class,
        ServerPropertiesAutoConfiguration.class,
        PropertyPlaceholderAutoConfiguration.class,
        ThymeleafAutoConfiguration.class,
        WebMvcAutoConfiguration.class,
        WebSocketAutoConfiguration.class,
})
public class SampleWebUiApplication {

Code was copied from this blog post.


The most voted answer so far is not wrong, but it doesn't go into the depth I like to see and provides no scientific evidence. The Spring Boot team went through an exercise for reducing startup time for Boot 2.0, and ticket 11226 contains a lot of useful information. There is also a ticket 7939 open to adding timing information to condition evaluation, but it doesn't seem to have a specific ETA.

The most useful, and methodical approach for debugging Boot startup has been done by Dave Syer. https://github.com/dsyer/spring-boot-startup-bench

I had a similar use case as well, so I took Dave's approach of micro-benchmarking with JMH and ran with it. The result is the boot-benchmark project. I designed it such that it can be used to measure startup time for any Spring Boot application, using the executable jar produced by bootJar (previously called bootRepackage in Boot 1.5) Gradle task. Feel free to use it and provide feedback.

My findings are as follows:

  1. CPU matters. A lot.
  2. Starting the JVM with -Xverify:none helps significantly.
  3. Excluding unnecessary autoconfigurations helps.
  4. Dave recommended JVM argument -XX:TieredStopAtLevel=1, but my tests didn't show significant improvement with that. Also, -XX:TieredStopAtLevel=1 would probably slow down your first request.
  5. There have been reports of hostname resolution being slow, but I didn't find it to be a problem for the apps I tested.

Spring Boot 2.2.M1 has added feature to support Lazy Initialization in Spring Boot.

By default, when an application context is being refreshed, every bean in the context is created and its dependencies are injected. By contrast, when a bean definition is configured to be initialized lazily it will not be created and its dependencies will not be injected until it’s needed.

Enabling Lazy Initialization Set spring.main.lazy-initialization to true

When to Enable Lazy Initialization

lazy initialization can offer significant improvements in start up time but there are some notable downsides too and it’s important to enable it with care

For more details please check Doc

Update:

Spring Boot Spring Boot 2.4.0 - Startup Endpoint

Spring Boot 2.4.0 has added a new Startup endpoint that can be used to identify beans that are taking longer than expected to start. You can get more details about the Application Startup tracking here


As described in this question/answer, I think the best approach is to instead of adding only those you think you need, exclude the dependencies you know you don't need.

See: Minimise Spring Boot Startup Time

In summary:

You can see what is going on under the covers and enable debug logging as simple as specifying --debug when starting the application from the command-line. You can also specify debug=true in your application.properties.

Also, you can set the logging level in application.properties as simple as:

logging.level.org.springframework.web: DEBUG logging.level.org.hibernate: ERROR

If you detect an auto-configured module you don't want, it can be disabled. The docs for this can be found here: http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#using-boot-disabling-specific-auto-configuration

An example would look like:

@Configuration
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
public class MyConfiguration {
}

Well there is entire list of possible actions described here: https://spring.io/blog/2018/12/12/how-fast-is-spring

I will put the most important notes from Spring side (adjusted a little bit):

  • Classpath exclusions from Spring Boot web starters:
    • Hibernate Validator
    • Jackson (but Spring Boot actuators depend on it). Use Gson if you need JSON rendering (only works with MVC out of the box).
    • Logback: use slf4j-jdk14 instead
  • Use the spring-context-indexer. It’s not going to add much, but every little helps.
  • Don’t use actuators if you can afford not to.
  • Use Spring Boot 2.1 and Spring 5.1. Switch to 2.2 and 5.2 when they are available.
  • Fix the location of the Spring Boot config file(s) with spring.config.location (command line argument or System property etc.). Example for testing in IDE: spring.config.location=file://./src/main/resources/application.properties.
  • Switch off JMX if you don’t need it with spring.jmx.enabled=false (this is the default in Spring Boot 2.2)
  • Make bean definitions lazy by default. There’s a new flag spring.main.lazy-initialization=true in Spring Boot 2.2 (use LazyInitBeanFactoryPostProcessor for older Spring).
  • Unpack the fat jar and run with an explicit classpath.
  • Run the JVM with -noverify. Also consider -XX:TieredStopAtLevel=1 (that will slow down the JIT later at the expense of the saved startup time).

The mentioned LazyInitBeanFactoryPostProcessor (you can use it for Spring 1.5 if you cannot apply flag spring.main.lazy-initialization=true available from Spring 2.2):

public class LazyInitBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

  @Override
  public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
      for (String beanName : beanFactory.getBeanDefinitionNames()) {
        BeanDefinition definition = beanFactory.getBeanDefinition(beanName);
        definition.setLazyInit(true);
      }
  }
}

You can also use (or write your own - it's simple) something to analyse beans initialization time: https://github.com/lwaddicor/spring-startup-analysis

Hope it helps!


If you're trying to optimize development turn-around for manual testing, I strongly recommend the use of devtools.

Applications that use spring-boot-devtools will automatically restart whenever files on the classpath change.

Just recompile -- and the server will restart itself (for Groovy you only need to update the source file). if you're using an IDE (e.g. 'vscode'), it may automatically compile your java files, so just saving a java file can initiate a server restart, indirectly -- and Java becomes just as seamless as Groovy in this regard.

The beauty of this approach is that the incremental restart short-circuits some of the from-scratch startup steps -- so your service will be back up and running much more quickly!


Unfortunately, this doesn't help with startup times for deployment or automated unit testing.