Spring Boot启动可以有多快?

点击左上角,关注:“锅外的大佬”

专注分享国外最新技术内容

帮助每位开发者更优秀地成长

"Spring有多快?" 这是2018年”Spring One Platfrom“大会的一个主题,我看了视频并亲自尝试了一下。所以我将在这篇文章中,介绍下我所做的事情以及结果。

没看过的推荐去看一下,蛮有意思的: https://springoneplatform.io/2018/sessions/how-fast-is-spring

本文源代码地址:https://github.com/bufferings/spring-boot-startup-mybench

我使用OpenJDK 11:

❯ 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)

你可以像下面一样运行基准测试,这需要点时间,因为会执行所有基准测试。

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

1.Flux Baseline

我用SpringInitializer创建一个只有 ReactiveWeb的项目,然后用 SpringMVC风格创建了一个 Controller

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

SpringBoot版本是 2.1.0RELEASE.

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

启动时间为2.938±0.287 s/op。

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

现在我得到一个对比启动时间的基线(baseline),让我们从这里开始。

2.WebMVC

我想知道 WebMVC怎么样,而不是 WebFlux。也许这仅仅意味着Tomcat和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更快点,对吧?

3.spring-context-indexer

接下来,我尝试了 spring-context-indexer,它似乎创建了主键索引

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

呃...变慢了一点?

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

我检查了 spring.components,发现它只包含一个组件。我明白了…我应该尝试一个更大的项目来了解效果。

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

4.Lazy Initialization

尝试懒初始化

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

结果如下,它只变快了一点儿。

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

5.No Verify

启动时使用 -noverify,不进行验证:

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

它变快了一点。我不知道这是什么意思,所以之后要查一下。

6.TieredStopAtLevel

启动时使用 -XX:TieredStopAtLevel=1

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

Uh!快了很多,启动时间接近两秒,但我还是不清楚为什么,稍后我会去查一下。

7.显式指定SpringConfigLocation

启动时使用 Dspring.config.location=classpath:/application.properties:

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

它变慢了...

8.关闭JMX

启动时使用 -Dspring.jmx.enabled=false:

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

它变得快了些。

9.排除Logback

到这,我尝试排除些依赖。首先,排除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>

结果如下:

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

好像稍微有点改进?

10.排除JackSon

下一个是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>

看结果:

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

变快了一点儿。

11.排除 HibernateValidator

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

结果:

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

也有一点改进。 排除依赖库到这就结束了。

12.AppCDS

AppCDS(应用程序类数据共享,Application Class Data Sharing)作为一个商业特性包含在Oracle JDK中。但它在OpenJDK 10中可用。

AppCDS似乎将信息转储到共享存档中,因此启动时间变得更短。

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

它没有变得更快,然后我查找了CDS的相关资料发现:使用Spring Boot FatJAR时,这些库不在 CDS的范围内。

13.Flux with Thin Launcher

抱歉,基准命名为‘Exploded’是不对的,一次我尝试暴露FatJar,但我仍然不能使用CDS。所以我现在使用 ThinLauncher,所以请把基准名称从 Exploded改为 ThinLauncher吧。

在使用CDS之前,我想检查下使用 ThinLauncher打包的速度。

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

虽然我使用 ThinLauncher来打包app,但是我没有使用 ThinLauncher的启动类,而是指定了Main类来让启动时间尽可能快些。

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

变快了点,对吧?

14.Thin Launcher + CDS

现在我要对它使用 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

Wow! 它变快了很多!

15.全部应用

最后,我把上面所有方法的都应用在程序上。

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

启动速度少于1秒钟!yeah!

16.还有一点

在Dave的会议上,他提到了“函数Bean定义”(Functional Bean Definitions),尝试在没有SpringBoot的情况下使用Spring进行改进,应用程序变得更快了。我需要学习更多来理解他们。

17.结果列表

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

感谢观看!

原文链接:https://dev.to/bufferings/lets-make-springboot-app-start-faster-k9m

作者:Mitz

译者:Lensen


推荐阅读:Spring Boot与Micronaut性能比较

上篇好文:Spring Cloud Kubernetes指南


640?wx_fmt=png


点下在看,和我一起帮助更多开发者!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值