Accelerate Spring Boot Time

I have a Spring Boot application. I added a lot of dependencies (unfortunately, I need all of them), and the startup time has greatly increased. Simple execution of SpringApplication.run(source, args) takes 10 seconds.

Although this is not so much compared to what they’re used to, I’m unhappy that it takes so much, mainly because it breaks the development process. The application itself is currently quite small, so I assume that most of the time it is associated with added dependencies, and not with the application classes themselves.

I assume the problem is scanning the classpath, but I'm not sure how:

  • Confirm that this is a problem (for example, how to "debug" Spring Boot)
  • If this is really the reason, how can I limit it to make it faster? For example, if I know that some kind of dependency or package does not contain anything that Spring should scan, is there a way to limit this?

I assume that the Spring extension for parallel initialization of the bean at startup will speed up the process, but this improvement request has been open since 2011 without any progress. I see some other efforts in Spring Boot itself, such as Investigate Tomcat JarScanning, speed improvement , but this is specific to Tomcat and was abandoned.

This article:

Although it focuses on integration tests, it suggests using lazy-init=true , however I don't know how to apply this to all beans in Spring Boot using the Java configuration - are there any pointers here?

Any (other) suggestions would be welcome.

+70
java performance spring spring-boot startup
Dec 01 '14 at 2:37
source share
10 answers

Spring Boot does a lot of automatic configuration that might not be needed. Thus, you can limit only the automatic configuration necessary for your application. To view a complete list of autoconfigurations, simply run the org.springframework.boot.autoconfigure registration in DEBUG mode ( logging.level.org.springframework.boot.autoconfigure=DEBUG in application.properties ). Another option is to start the spring boot application with the --debug option: java -jar myproject-0.0.1-SNAPSHOT.jar --debug

The output will be something like this:

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

View this list and enable only the necessary autoconfigurations:

 @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 .

+42
Mar 14 '16 at 17:24
source share

So far, the vote with the highest number of votes is not incorrect, but it does not go deep into what I like to see and does not provide any scientific evidence. The Spring Boot team conducted an exercise to reduce the startup time of Boot 2.0, and ticket 11226 contains a lot of useful information. There is also ticket 7939, open to add time information to the status assessment, but it does not seem to have a specific ETA.

The most useful and methodical approach to debugging boot launches was made by Dave Sayer. https://github.com/dsyer/spring-boot-startup-bench

I had a similar use case, so I applied Dave's approach to microprocessors with JMH and ran with it. The result is a bootstrapping project. I designed it so that it can be used to measure the startup time of any Spring Boot application using the jar executable created by bootJar (previously called bootRepackage in Boot 1.5), the Gradle task. Feel free to use it and leave a review.

My findings are as follows:

  1. CPU matters. A lot of.
  2. Running JVM with -Xverify: no one helps significantly.
  3. Eliminating unnecessary auto configurations helps.
  4. Dave recommended the JVM -XX argument : TieredStopAtLevel = 1 , but my tests did not show a significant improvement with this. Also, -XX:TieredStopAtLevel=1 will probably slow down your first request.
  5. There were reports of slow resolving of the host name, but I did not find this to be a problem for the applications I tested.
+20
Apr 05 '18 at 2:07
source share

As described in this question / answer, I believe that it is best to use instead of adding only those that you think you need, exclude dependencies that you know you do not need.

See: Minimize Spring Startup Time

In short:

You can see what is happening under the covers, and turning on debug logging is as simple as specifying --debug when you run the application from the command line. You can also specify debug = true in your application.properties.

Alternatively, 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 find a module with automatic configuration that you do not need, you can disable it. Documents 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 this:

 @Configuration @EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class}) public class MyConfiguration { } 
+6
Sep 22 '16 at 14:44
source share

Spring Boot 2.2.M1 adds support for deferred initialization in Spring Boot.

By default, when updating the application context, each component in the context is created and its dependencies are implemented. In contrast, when a bean definition is configured for lazy initialization, it will not be created, and its dependencies will not be implemented until it is needed.

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

For more details, please check the dock.

+3
Mar 20 '19 at 13:00
source share

If you are trying to optimize the development process for manual testing, I highly recommend using devtools .

Applications using spring-boot-devtools will automatically restart whenever files in the classpath change.

Just recompile and the server will reboot itself (for Groovy you only need to update the source file). If you use an IDE (for example, "vscode"), it can automatically compile your java files, so just saving a java file can initiate a server restart indirectly - and Java in this regard becomes as hassle-free as Groovy.

The beauty of this approach is that an incremental restart causes a short circuit at some stages of starting from scratch, so your service will run faster and faster!




Unfortunately, this does not help with startup time for deployment or automatic unit testing.

0
Dec 12 '18 at 21:44
source share

There is only one guaranteed way to develop what is happening here, namely to profile your application and find the hot spots that cause the problem.

I recommend using YourKit. It has a very good IDE integration, so you can profile your application from Eclipse or whatever. See here

https://www.yourkit.com/docs/java/help/local_profiling.jsp

You can very quickly find out what causes the problem, and then you can send it here for possible solutions.

-one
Apr 02 '15 at 9:54 on
source share

You can try my FastClasspathScanner library. I don't know if you can use Spring to work with it, but it scans the classpath much faster than Spring.

-one
Sep 24 '15 at 15:19
source share

I find it strange that no one has offered these optimizations before. Here are some general tips for optimizing your build and launching a project during development:

  • exclude development directories from the anti-virus scanner:
    • project catalog
    • build the output directory (if it is outside the project directory)
    • IDE index directory (e.g. ~ / .IntelliJIdea2018.3)
    • deployment directory (web applications in Tomcat)
  • upgrade equipment. use a faster CPU and RAM, an improved Internet connection (for downloading dependencies) and a database connection, switch to SSD. the graphics card does not matter.

WARNINGS

  1. The first option comes at the price of reduced security.
  2. the second option costs money (obviously).
-2
Jan 01 '19 at 22:05
source share

WARNING. If you do not use Hibernate DDL to automatically generate a database schema and do not use the L2 cache, this answer does NOT apply to you. Scroll forward.

I found that Hibernate significantly increases the launch time of the application. Disabling the L2 cache and initializing the database leads to a faster launch of the Spring Boot application. Leave the cache enabled for production and disable it for your development environment.

application.yml:

 spring: jpa: generate-ddl: false hibernate: ddl-auto: none properties: hibernate: cache: use_second_level_cache: false use_query_cache: false 

Test results:

  1. L2 cache is enabled and ddl-auto: update

     INFO 5024 --- [restartedMain] osweb.context.ContextLoader : Root WebApplicationContext: initialization completed in 23331 ms INFO 5024 --- [restartedMain] bnspring.Application : Started Application in 54.251 seconds (JVM running for 63.766) 
  2. L2 cache is off and ddl-auto: none

     INFO 10288 --- [restartedMain] osweb.context.ContextLoader : Root WebApplicationContext: initialization completed in 9863 ms INFO 10288 --- [restartedMain] bnspring.Application : Started Application in 32.058 seconds (JVM running for 37.625) 

Now I wonder what I will do with all this free time?

-2
Jan 01 '19 at 22:27
source share

It seems to me that you are using the wrong configuration parameter. Start by checking myContainer and potential conflicts. To determine who uses most of the resources, you need to check the memory cards (see Data Amount!) For each dependency at a time - and this takes a lot of time ... (and SUDO privileges). By the way: do you usually check the code for dependencies?

-6
Mar 30 '15 at 13:15
source share



All Articles