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

专注分享国外最新技术内容
帮助每位开发者更优秀地成长
"Spring有多快?" 这是2018年”Spring One Platfrom“大会的一个主题,我看了视频并亲自尝试了一下。所以我将在这篇文章中,介绍下我所做的事情以及结果。
没看过的推荐去看一下,蛮有意思的: https://springoneplatform.io/2018/sessions/how-fast-is-spring
本文源代码地址:https://github.com/bufferings/spring-boot-startup-mybench
我使用OpenJDK 11:
  1. java --version
  2. openjdk 11.0.12018-10-16
  3. OpenJDKRuntimeEnvironment18.9(build 11.0.1+13)
  4. OpenJDK64-BitServer VM 18.9(build 11.0.1+13, mixed mode)
你可以像下面一样运行基准测试,这需要点时间,因为会执行所有基准测试。
  1. ./mvnw clean package
  2. (cd benchmarks/; java -jar target/benchmarks.jar)

1.Flux Baseline

我用SpringInitializer创建一个只有 ReactiveWeb的项目,然后用 SpringMVC风格创建了一个 Controller
  1. @SpringBootApplication
  2. @RestController
  3. publicclassDemoApplication{
  4. @GetMapping("/")
  5. publicString home(){
  6. return"Hello";
  7. }
  8. publicstaticvoid main(String[] args){
  9. SpringApplication.run(DemoApplication.class, args);
  10. }
  11. }
SpringBoot版本是 2.1.0RELEASE.
  1. <parent>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-parent</artifactId>
  4. <version>2.1.0.RELEASE</version>
  5. <relativePath/><!-- lookup parent from repository -->
  6. </parent>
启动时间为2.938±0.287 s/op。
  1. BenchmarkModeCntScoreErrorUnits
  2. MyBenchmark.case01_FluxBaseline ss 102.938±0.287 s/op
现在我得到一个对比启动时间的基线(baseline),让我们从这里开始。

2.WebMVC

我想知道 WebMVC怎么样,而不是 WebFlux。也许这仅仅意味着Tomcat和Netty之间的比较呢?
  1. BenchmarkModeCntScoreErrorUnits
  2. MyBenchmark.case01_FluxBaseline ss 102.938±0.287 s/op
  3. MyBenchmark.case02_Web ss 103.281±0.342 s/op
WebFlux更快点,对吧?

3.spring-context-indexer

接下来,我尝试了 spring-context-indexer,它似乎创建了主键索引
  1. <dependency>
  2. <groupId>org.springframework</groupId>
  3. <artifactId>spring-context-indexer</artifactId>
  4. <optional>true</optional>
  5. </dependency>
呃...变慢了一点?
  1. BenchmarkModeCntScoreErrorUnits
  2. MyBenchmark.case01_FluxBaseline ss 102.938±0.287 s/op
  3. MyBenchmark.case03_WithContextIndexer ss 103.063±0.102 s/op
我检查了 spring.components,发现它只包含一个组件。我明白了…我应该尝试一个更大的项目来了解效果。
  1. #SunNov0418:42:59 JST 2018
  2. com.example.DemoApplication=org.springframework.stereotype.Component

4.Lazy Initialization

尝试懒初始化
  1. @Configuration
  2. publicclassLazyInitBeanFactoryPostProcessorimplementsBeanFactoryPostProcessor{
  3. @Override
  4. publicvoid postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)throwsBeansException{
  5. for(String beanName : beanFactory.getBeanDefinitionNames()){
  6. beanFactory.getBeanDefinition(beanName).setLazyInit(true);
  7. }
  8. }
结果如下,它只变快了一点儿。
  1. BenchmarkModeCntScoreErrorUnits
  2. MyBenchmark.case01_FluxBaseline ss 102.938±0.287 s/op
  3. MyBenchmark.case04_WithLazyInit ss 102.844±0.129 s/op

5.No Verify

启动时使用 -noverify,不进行验证:
  1. BenchmarkModeCntScoreErrorUnits
  2. MyBenchmark.case01_FluxBaseline ss 102.938±0.287 s/op
  3. MyBenchmark.case05_WithNoVerifyOption ss 102.582±0.060 s/op
它变快了一点。我不知道这是什么意思,所以之后要查一下。

6.TieredStopAtLevel

启动时使用 -XX:TieredStopAtLevel=1
  1. BenchmarkModeCntScoreErrorUnits
  2. MyBenchmark.case01_FluxBaseline ss 102.938±0.287 s/op
  3. MyBenchmark.case06_WithTieredStopAtLevel1Option ss 101.980±0.037 s/op
Uh!快了很多,启动时间接近两秒,但我还是不清楚为什么,稍后我会去查一下。

7.显式指定SpringConfigLocation

启动时使用 Dspring.config.location=classpath:/application.properties:
  1. BenchmarkModeCntScoreErrorUnits
  2. MyBenchmark.case01_FluxBaseline ss 102.938±0.287 s/op
  3. MyBenchmark.case07_WithSpringConfigLocationOption ss 103.026±0.139 s/op
它变慢了...

8.关闭JMX

启动时使用 -Dspring.jmx.enabled=false:
  1. BenchmarkModeCntScoreErrorUnits
  2. MyBenchmark.case01_FluxBaseline ss 102.938±0.287 s/op
  3. MyBenchmark.case08_WithJmxDisabledOption ss 102.877±0.097 s/op
它变得快了些。

9.排除Logback

到这,我尝试排除些依赖。首先,排除Logback
  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-webflux</artifactId>
  4. <exclusions>
  5. <exclusion>
  6. <artifactId>spring-boot-starter-logging</artifactId>
  7. <groupId>org.springframework.boot</groupId>
  8. </exclusion>
  9. </exclusions>
  10. </dependency>
  11. <dependency>
  12. <groupId>org.slf4j</groupId>
  13. <artifactId>slf4j-jdk14</artifactId>
  14. </dependency>
结果如下:
  1. BenchmarkModeCntScoreErrorUnits
  2. MyBenchmark.case01_FluxBaseline ss 102.938±0.287 s/op
  3. MyBenchmark.case09_WithoutLogback ss 102.904±0.096 s/op
好像稍微有点改进?

10.排除JackSon

下一个是JackSon:
  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-webflux</artifactId>
  4. <exclusions>
  5. <exclusion>
  6. <artifactId>spring-boot-starter-json</artifactId>
  7. <groupId>org.springframework.boot</groupId>
  8. </exclusion>
  9. </exclusions>
  10. </dependency>
看结果:
  1. BenchmarkModeCntScoreErrorUnits
  2. MyBenchmark.case01_FluxBaseline ss 102.938±0.287 s/op
  3. MyBenchmark.case10_WithoutJackson ss 102.789±0.093 s/op
变快了一点儿。

11.排除 HibernateValidator

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-webflux</artifactId>
  4. <exclusions>
  5. <exclusion>
  6. <artifactId>hibernate-validator</artifactId>
  7. <groupId>org.hibernate.validator</groupId>
  8. </exclusion>
  9. </exclusions>
  10. </dependency>
结果:
  1. BenchmarkModeCntScoreErrorUnits
  2. MyBenchmark.case01_FluxBaseline ss 102.938±0.287 s/op
  3. MyBenchmark.case11_WithoutHibernateValidator ss 102.857±0.084 s/op
也有一点改进。 排除依赖库到这就结束了。

12.AppCDS

AppCDS(应用程序类数据共享,Application Class Data Sharing)作为一个商业特性包含在Oracle JDK中。但它在OpenJDK 10中可用。
AppCDS似乎将信息转储到共享存档中,因此启动时间变得更短。
  1. BenchmarkModeCntScoreErrorUnits
  2. MyBenchmark.case01_FluxBaseline ss 102.938±0.287 s/op
  3. MyBenchmark.case12_WithAppCds ss 102.957±0.079 s/op
它没有变得更快,然后我查找了CDS的相关资料发现:使用Spring Boot FatJAR时,这些库不在 CDS的范围内。

13.Flux with Thin Launcher

抱歉,基准命名为‘Exploded’是不对的,一次我尝试暴露FatJar,但我仍然不能使用CDS。所以我现在使用 ThinLauncher,所以请把基准名称从 Exploded改为 ThinLauncher吧。
在使用CDS之前,我想检查下使用 ThinLauncher打包的速度。
  1. <plugins>
  2. <plugin>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-maven-plugin</artifactId>
  5. <dependencies>
  6. <dependency>
  7. <groupId>org.springframework.boot.experimental</groupId>
  8. <artifactId>spring-boot-thin-layout</artifactId>
  9. <version>1.0.15.RELEASE</version>
  10. </dependency>
  11. </dependencies>
  12. </plugin>
  13. </plugins>
虽然我使用 ThinLauncher来打包app,但是我没有使用 ThinLauncher的启动类,而是指定了Main类来让启动时间尽可能快些。
  1. BenchmarkModeCntScoreErrorUnits
  2. MyBenchmark.case01_FluxBaseline ss 102.938±0.287 s/op
  3. MyBenchmark.case13_Exploded ss 102.476±0.091 s/op
变快了点,对吧?

14.Thin Launcher + CDS

现在我要对它使用 AppCDS了。
  1. BenchmarkModeCntScoreErrorUnits
  2. MyBenchmark.case01_FluxBaseline ss 102.938±0.287 s/op
  3. MyBenchmark.case14_ExplodedWithAppCds ss 101.535±0.036 s/op
Wow! 它变快了很多!

15.全部应用

最后,我把上面所有方法的都应用在程序上。
  1. BenchmarkModeCntScoreErrorUnits
  2. MyBenchmark.case01_FluxBaseline ss 102.938±0.287 s/op
  3. MyBenchmark.case15_AllApplied ss 100.801±0.037 s/op
启动速度少于1秒钟!yeah!

16.还有一点

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

17.结果列表

  1. BenchmarkModeCntScoreErrorUnits
  2. MyBenchmark.case01_FluxBaseline ss 102.938±0.287 s/op
  3. MyBenchmark.case02_Web ss 103.281±0.342 s/op
  4. MyBenchmark.case03_WithContextIndexer ss 103.063±0.102 s/op
  5. MyBenchmark.case04_WithLazyInit ss 102.844±0.129 s/op
  6. MyBenchmark.case05_WithNoVerifyOption ss 102.582±0.060 s/op
  7. MyBenchmark.case06_WithTieredStopAtLevel1Option ss 101.980±0.037 s/op
  8. MyBenchmark.case07_WithSpringConfigLocationOption ss 103.026±0.139 s/op
  9. MyBenchmark.case08_WithJmxDisabledOption ss 102.877±0.097 s/op
  10. MyBenchmark.case09_WithoutLogback ss 102.904±0.096 s/op
  11. MyBenchmark.case10_WithoutJackson ss 102.789±0.093 s/op
  12. MyBenchmark.case11_WithoutHibernateValidator ss 102.857±0.084 s/op
  13. MyBenchmark.case12_WithAppCds ss 102.957±0.079 s/op
  14. MyBenchmark.case13_Exploded ss 102.476±0.091 s/op
  15. MyBenchmark.case14_ExplodedWithAppCds ss 101.535±0.036 s/op
  16. MyBenchmark.case15_AllApplied ss 100.801±0.037 s/op
感谢观看!
原文链接:https://dev.to/bufferings/lets-make-springboot-app-start-faster-k9m
作者:Mitz
译者:Lensen




点下在看,和我一起帮助更多开发者!
继续阅读
阅读原文