11 Points Make Your Spring Boot Start Faster

Keywords: Java Spring WebFlux Hibernate

Preface

OpenJDK 11 is used.

java --version
openjdk 11.0.1 2018-10-16
OpenJDK Runtime Environment 18.9 (build 11.0.1+13)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.1+13, mixed mode)

You can run the benchmark as follows. It may take some time to run, and all the tests will be executed below.

./mvnw clean package
(cd benchmarks/; java -jar target/benchmarks.jar)

FluxBaseline

Create a project using Spring Initializr, which contains only Reactive Web. Next, I'll write a minimalist controller in WebMVC style.

@SpringBootApplication
@RestController
public class DemoApplication {
 @GetMapping("/")
 public String home() {
 return "Hello";
 }
 public static void main(String[] args) {
 SpringApplication.run(DemoApplication.class, args);
 }
}

Spring Boot version is 2.1.0.RELEASE.

<parent>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-parent</artifactId>
 <version>2.1.0.RELEASE</version>
 <relativePath/> <!-- lookup parent from repository -->
</parent>

The result of start-up was 2.938 +0.287 s/op.

Benchmark Mode Cnt Score Error Units
MyBenchmark.case01_FluxBaseline ss 10 2.938 ± 0.287 s/op

Now, take this result as the baseline. Let's start here.

Welcome everyone to pay attention to my public giant [programmer chasing wind], articles will be updated in it, collated information will also be placed in it.

WebMVC

I wonder why WebMVC is used instead of WebFlux. I tried. Maybe just to compare Tomcat and Netty?

Benchmark Mode Cnt Score Error Units
MyBenchmark.case01_FluxBaseline ss 10 2.938 ± 0.287 s/op
MyBenchmark.case02_Web ss 10 3.281 ± 0.342 s/op

WebFlux is a little faster, isn't it?

spring-context-indexer

Next, I tried spring-context-indexer, which seemed to create component index.

<dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-context-indexer</artifactId>
 <optional>true</optional>
</dependency>

Um... A little slower?

Benchmark Mode Cnt Score Error Units
MyBenchmark.case01_FluxBaseline ss 10 2.938 ± 0.287 s/op
MyBenchmark.case03_WithContextIndexer ss 10 3.063 ± 0.102 s/op

I checked spring.components and found that only one component was included. Understand... I should try a bigger project so that I can see the effect.

#
#Sun Nov 04 18:42:59 JST 2018
com.example.DemoApplication=org.springframework.stereotype.Component

lazy initialization

Lazy initialization was attempted.

@Configuration
public class LazyInitBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
 @Override
 public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
 for (String beanName : beanFactory.getBeanDefinitionNames()) {
 beanFactory.getBeanDefinition(beanName).setLazyInit(true);
 }
 }
}

Looking at the results, the boot is a little faster.

Benchmark Mode Cnt Score Error Units
MyBenchmark.case01_FluxBaseline ss 10 2.938 ± 0.287 s/op
MyBenchmark.case04_WithLazyInit ss 10 2.844 ± 0.129 s/op

NoVerify

Run the add-noverify option:

Benchmark Mode Cnt Score Error Units
MyBenchmark.case01_FluxBaseline ss 10 2.938 ± 0.287 s/op
MyBenchmark.case05_WithNoVerifyOption ss 10 2.582 ± 0.060 s/op

Start up a little faster. I don't know why there is such a result, but I need to understand it carefully later.

TieredStopAtLevel

Run the add-XX:TieredStopAtLevel=1 option:

Benchmark Mode Cnt Score Error Units
MyBenchmark.case01_FluxBaseline ss 10 2.938 ± 0.287 s/op
MyBenchmark.case06_WithTieredStopAtLevel1Option ss 10 1.980 ± 0.037 s/op

Well, much faster! Reduced by almost 2 seconds. I still don't know what the meaning of this parameter is. I need to understand it carefully later.

Specify the Spring ConfigLocation parameter

Run the add-Dspring.config.location=classpath:/application.properties option:

Benchmark Mode Cnt Score Error Units
MyBenchmark.case01_FluxBaseline ss 10 2.938 ± 0.287 s/op
MyBenchmark.case07_WithSpringConfigLocationOption ss 10 3.026 ± 0.139 s/op

Well, it's slowing down again.

Close JMX

Run the add - Dspring.jmx.enabled=false option:

Benchmark Mode Cnt Score Error Units
MyBenchmark.case01_FluxBaseline ss 10 2.938 ± 0.287 s/op
MyBenchmark.case08_WithJmxDisabledOption ss 10 2.877 ± 0.097 s/op

It's getting a little faster.

Cancel Logback

From here on, I began to reduce the library. To begin, cancel Logback:

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-webflux</artifactId>
 <exclusions>
 <exclusion>
 <artifactId>spring-boot-starter-logging</artifactId>
 <groupId>org.springframework.boot</groupId>
 </exclusion>
 </exclusions>
</dependency>
<dependency>
 <groupId>org.slf4j</groupId>
 <artifactId>slf4j-jdk14</artifactId>
</dependency>

The results are as follows:

Benchmark Mode Cnt Score Error Units
MyBenchmark.case01_FluxBaseline ss 10 2.938 ± 0.287 s/op
MyBenchmark.case09_WithoutLogback ss 10 2.904 ± 0.096 s/op

Um... Does it seem to have improved a little?

Cancel Jackson

Next comes Jackson

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-webflux</artifactId>
 <exclusions>
 <exclusion>
 <artifactId>spring-boot-starter-json</artifactId>
 <groupId>org.springframework.boot</groupId>
 </exclusion>
 </exclusions>
</dependency>

The results are as follows:

Benchmark Mode Cnt Score Error Units
MyBenchmark.case01_FluxBaseline ss 10 2.938 ± 0.287 s/op
MyBenchmark.case10_WithoutJackson ss 10 2.789 ± 0.093 s/op

It turned out a little faster.

Cancel Hibernate Validator

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-webflux</artifactId>
 <exclusions>
 <exclusion>
 <artifactId>hibernate-validator</artifactId>
 <groupId>org.hibernate.validator</groupId>
 </exclusion>
 </exclusions>
</dependency>

The results are as follows:

Benchmark Mode Cnt Score Error Units
MyBenchmark.case01_FluxBaseline ss 10 2.938 ± 0.287 s/op
MyBenchmark.case11_WithoutHibernateValidator ss 10 2.857 ± 0.084 s/op

It also has some effect.

So far, the library is no longer cancelled.

AppCDS

AppCDS (Application Class Data Sharing) is an enterprise version of Oracle JDK. OpenJDK 10 began to include this feature.

AppCDS dumps seem to be stored in a shared compressed file, so the startup time is shorter.

Benchmark Mode Cnt Score Error Units
MyBenchmark.case01_FluxBaseline ss 10 2.938 ± 0.287 s/op
MyBenchmark.case12_WithAppCds ss 10 2.957 ± 0.079 s/op

Um... It's not getting faster. Then I read CDS articles and found out why.

SpringBoot FatJAR is not covered by CDS management.

Using Thin Launcher's Flux

Well, I'm sorry, the "Exploded" benchmark was wrong. I tried to use FatJAR, but CDS couldn't. So I turned to Thin Launcher, so "Exploded" became "Thin Launche".

Before using CDS, I'll test the startup speed of packaging JAR files with Thin Launcher.

<plugins>
 <plugin>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-maven-plugin</artifactId>
 <dependencies>
 <dependency>
 <groupId>org.springframework.boot.experimental</groupId>
 <artifactId>spring-boot-thin-layout</artifactId>
 <version>1.0.15.RELEASE</version>
 </dependency>
 </dependencies>
 </plugin>
</plugins>

Although I use Thin Launcher to package app s, instead of using Thin Launcher to start classes, I use Main class to start as fast as possible.

Benchmark Mode Cnt Score Error Units
MyBenchmark.case01_FluxBaseline ss 10 2.938 ± 0.287 s/op
MyBenchmark.case13_Exploded ss 10 2.476 ± 0.091 s/op

Well, a little faster, right?

Thin Launcher + CDS

Now, I'm going to use AppCDS.

Benchmark Mode Cnt Score Error Units
MyBenchmark.case01_FluxBaseline ss 10 2.938 ± 0.287 s/op
MyBenchmark.case14_ExplodedWithAppCds ss 10 1.535 ± 0.036 s/op

Oh! It's getting faster!

All operations are on

Ultimately, I used all the operations.

Benchmark Mode Cnt Score Error Units
MyBenchmark.case01_FluxBaseline ss 10 2.938 ± 0.287 s/op
MyBenchmark.case15_AllApplied ss 10 0.801 ± 0.037 s/op

Less than 1 second! (')

Further more

In Dave's video, he mentioned "Functional Bean Definition" and tried to use Spring only instead of Spring Boot, app became faster. The reasons need to be further understood.

Result:

Benchmark Mode Cnt Score Error Units
MyBenchmark.case01_FluxBaseline ss 10 2.938 ± 0.287 s/op
MyBenchmark.case02_Web ss 10 3.281 ± 0.342 s/op
MyBenchmark.case03_WithContextIndexer ss 10 3.063 ± 0.102 s/op
MyBenchmark.case04_WithLazyInit ss 10 2.844 ± 0.129 s/op
MyBenchmark.case05_WithNoVerifyOption ss 10 2.582 ± 0.060 s/op
MyBenchmark.case06_WithTieredStopAtLevel1Option ss 10 1.980 ± 0.037 s/op
MyBenchmark.case07_WithSpringConfigLocationOption ss 10 3.026 ± 0.139 s/op
MyBenchmark.case08_WithJmxDisabledOption ss 10 2.877 ± 0.097 s/op
MyBenchmark.case09_WithoutLogback ss 10 2.904 ± 0.096 s/op
MyBenchmark.case10_WithoutJackson ss 10 2.789 ± 0.093 s/op
MyBenchmark.case11_WithoutHibernateValidator ss 10 2.857 ± 0.084 s/op
MyBenchmark.case12_WithAppCds ss 10 2.957 ± 0.079 s/op
MyBenchmark.case13_Exploded ss 10 2.476 ± 0.091 s/op
MyBenchmark.case14_ExplodedWithAppCds ss 10 1.535 ± 0.036 s/op
MyBenchmark.case15_AllApplied ss 10 0.801 ± 0.037 s/op

It's really interesting. Thank!


Last

Welcome to communicate with us, like the article, remember to point a compliment, thank you for your support.


Posted by ronniebrown on Thu, 12 Sep 2019 00:20:11 -0700