javascript
如何让 Spring Boot 启动的更快?
點擊上方“朱小廝的博客”,選擇“設為星標”
回復”666“獲取新整理的1000+GB資料
來源:http://rrd.me/ekc64
“Spring有多快?”
這是 2018 Spring One Platform 中的一場會議。看完會議視頻,我自己動手試了一下。下面是我做出的測試結果。
還沒有觀看視頻的朋友推薦看一下,非常有意思。
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
我使用 SpringInitializr 創建項目,僅包含 Reactive Web。接下來,我會寫一個 WebMVC 風格的極簡controller。
@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/opWebFlux 快了一點,難道不是嗎?
3. spring-context-indexer
接下來,我試了 spring-context-indexer,似乎創建了 component index。
<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.Component4. 惰性初始化
嘗試了惰性初始化。
@Configuration public?class?LazyInitBeanFactoryPostProcessor?implements?BeanFactoryPostProcessor?{@Overridepublic?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/op5. NoVerify
運行加 -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
從這里開始,我開始減少函數庫。開始,取消 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的相關文章,找到原因了。
SpringBoot FatJAR 不在 CDS 管理范圍內。
13. 使用 Thin Launcher 的 Flux
嗯,對不起,“Exploded” 基準測試錯了。我曾經試著使用 FatJAR,但是 CDS 不能這么干。所以,我轉而使用 Thin Launcher,所以 “Exploded” 就變成了 “Thin Launche”。
使用 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 打包 app,但并沒有使用 Thin Launcher 啟動類,而是使用 Main class 讓啟動盡可能快一些。
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秒鐘!(∩′?`)∩耶
更進一步
在 Dave 的視頻中,他提到了“函數式 Bean 定義”,嘗試僅使用 Spring 不用 SpringBoot,app變得更快了。其中的道理還需要進一步了解。
結果:
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真的很有意思。感謝!
想知道更多?掃描下面的二維碼關注我
加技術群入口(備注:Tech):
免費星球入口:
最近整理了一份資料,包含Java技術棧、消息中間件、分布式存儲、大數據、高可用架構、通用型技術架構等。獲取方式:點擊「在看」,關注公眾號并在后臺回復“666”即可獲取。
朕已閱?
總結
以上是生活随笔為你收集整理的如何让 Spring Boot 启动的更快?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 刁钻!你和队友之间选一个淘汰,你怎么选?
- 下一篇: 中秋水文 | 安利一发国漫