“春天有多快?”
是Spring One Platform 2018的一个环节。我观看了视频并亲自尝试了一下。 因此,我在这里介绍我的工作和结果。
如果您尚未观看此会议视频,我建议您观看。 真有趣
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. FluxBaseline
↓我仅通过Reactive Web使用SpringInitializr创建了一个项目。 然后,我编写了一个具有WebMVC样式的微型控制器。
@SpringBootApplication
@RestController
public class DemoApplication {
@GetMapping("/")
public String home() {
return "Hello";
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
↓Spring Boot的版本是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>
↓开始需要2.938±0.287 s / op。
Benchmark Mode Cnt Score Error Units
MyBenchmark.case01_FluxBaseline ss 10 2.938 ± 0.287 s/op
现在,我有了一个基准来检查启动时间。 让我们从这里开始。
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
↓我检查了弹簧组件,发现它只包含1个组件。 我知道...我应该尝试做一个更大的项目才能知道效果。
#
#Sun Nov 04 18:42:59 JST 2018
com.example.DemoApplication=org.springframework.stereotype.Component
4.延迟初始化
尝试懒惰初始化。
@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.否验证
与-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
嗯,快多了! 花费了不到2秒的时间。 但是我也不知道这个标志。 所以我稍后再检查。
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:
<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.排除杰克逊
接下来是杰克逊
<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
Oracle JDK中包含AppCDS(应用程序类数据共享)作为一项商业功能。 但是它可以从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 Fat JAR,这些库不在CDS的范围内。
13.带有薄启动器的助焊剂
嗯,很抱歉,基准名称“ Exploded”是错误的。 曾经尝试爆炸FatJAR,但毕竟无法将CDS与爆炸的JAR一起使用。 因此,我切换为使用Thin Launcher。 请使用基准名称“爆炸”作为“ Thin Launcher”。
在使用CDS之前,我想检查一下Thin Launcher打包的JAR文件的速度。
<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>
尽管我使用Thin Launcher打包应用程序,但是我没有使用Thin Launcher的启动类,而是指定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
哇! 它变得更快了!
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秒! (∩´∀`)∩yay
更进一步
在Dave的会议上,他提到了“ Functional Bean Definitions”,尝试在不使用SpringBoot的情况下使用Spring进行改进,并且该应用程序变得更快。 我需要了解更多以了解它们。
结果清单
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
真的很有趣。 谢谢!