天天看點

Spring Boot 2.4新特性:節省95%記憶體占用

GraalVM是一種高性能的虛拟機,它可以顯著的提高程式的性能和運作效率,非常适合微服務。最近比較火的 Java 架構 Quarkus預設支援 GraalVM

下圖為 Quarkus 和傳統架構(SpringBoot) 等對比圖,更快的啟動資料、更小的記憶體消耗、更短的服務響應。

Spring Boot 2.4新特性:節省95%記憶體占用
Spring Boot 2.4 開始逐漸提供對 GraalVM 的支援,旨在提升上文所述的 啟動、記憶體、響應的使用體驗。

https://blog.didispace.com/spring-boot-2-4-feature-mem-95/#%E5%AE%89%E8%A3%85-GraalVM 安裝 GraalVM

  • 目前官方社群版本最新為 20.3.0 ,是基于 OpenJDK 8u272 and 11.0.9 定制的,可以了解為 OpenJDK 的衍生版本 。
Spring Boot 2.4新特性:節省95%記憶體占用
  • 官方推薦的是 SDKMAN[3] 用于快速安裝和切換不同版本 JDK 的工具 ,類似于 nodejs 的 nvm[4]。

使用類似指令即可完成指定版本安裝和指定預設版本

sdk install java 11.0.9.hs-adpt
sdk default java 11.0.9.hs-adpt      

不過安裝過程中需要從國外下載下傳相關資源 ,筆者在嘗試後使用體驗并不是很好,所有建議大家下載下傳指定版本 GraalVM 安裝即可(和 JDK 安裝方式一樣)。

  • 安裝成功檢視版本
⋊> ~ java -version                                                      11:30:34
openjdk version "11.0.9" 2020-10-20
OpenJDK Runtime Environment GraalVM CE 20.3.0 (build 11.0.9+10-jvmci-20.3-b06)
OpenJDK 64-Bit Server VM GraalVM CE 20.3.0 (build 11.0.9+10-jvmci-20.3-b06, mixed mode, sharing)      

安裝 native-image

native-image 是由 Oracle Labs 開發的一種 AOT 編譯器,應用所需的 class 依賴項及 runtime 庫打包編譯生成一個單獨可執行檔案。具有高效的 startup 及較小的運作時記憶體開銷的優勢。

但 GraalVM 并未内置隻是提供 gu 安裝工具,需要我們單獨安裝。

- 切換到 jdk 的安裝目錄
⋊> ~ cd $JAVA_HOME/bin/

- 使用gu指令安裝
⋊>  ./gu install native-image      

初始化 Spring Boot 2.4 項目

  • Spring Initializr 建立 demo 項目
curl https://start.spring.io/starter.zip -d dependencies=web \
           -d bootVersion=2.4.1 -o graal-demo.zip      
  • 先看一下啟動基準資料 , 單純運作空項目 需要 1135 ms 秒
java -jar demo-0.0.1-SNAPSHOT.jar


engine: [Apache Tomcat/9.0.41]
2020-12-18 11:48:36.856  INFO 91457 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2020-12-18 11:48:36.856  INFO 91457 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1135 ms      
  • 記憶體占用情況
ps aux | grep demo-0.0.1-SNAPSHOT.jar | grep -v grep | awk '{print $11 "\t" $6/1024"MB" }'
/usr/bin/java 480.965MB      

支援 GraalVM

  • 增加相關依賴,涉及插件較多完整已上傳 Gitee Gist[5]
<!-- 新增的部分,注意需要增加  spring maven 倉庫位址才能下載下傳到-->
<dependency>
    <groupId>org.springframework.experimental</groupId>
    <artifactId>spring-graalvm-native</artifactId>
    <version>0.8.3</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-indexer</artifactId>
</dependency>

<!--需要添加 spring maven 倉庫下載下傳 spring-graalvm-native-->
<repositories>
  <repository>
      <id>spring-milestones</id>
      <name>Spring Milestones</name>
      <url>https://repo.spring.io/milestone</url>
  </repository>
</repositories>      
  • Main 方法修改,增加屬性 proxyBeanMethods = false
@SpringBootApplication(proxyBeanMethods = false)      
  • 使用 native-image 建構可執行檔案
mvn -Pnative package
#建構過程比較慢,日志如下
spring.factories files...
[com.example.demo.demoapplication:93430]    classlist:   4,633.58 ms,  1.18 GB
   _____                     _                             _   __           __     _
  / ___/    ____    _____   (_)   ____    ____ _          / | / /  ____ _  / /_   (_) _   __  ___
  \__ \    / __ \  / ___/  / /   / __ \  / __ `/         /  |/ /  / __ `/ / __/  / / | | / / / _ \
 ___/ /   / /_/ / / /     / /   / / / / / /_/ /         / /|  /  / /_/ / / /_   / /  | |/ / /  __/
/____/   / .___/ /_/     /_/   /_/ /_/  \__, /         /_/ |_/   \__,_/  \__/  /_/   |___/  \___/
        /_/                            /____/

...
[com.example.demo.demoapplication:93430]      [total]: 202,974.38 ms,  4.23 GB      
  • 編譯結果

在 targe 目錄生成 名稱為

com.example.demo.demoapplication

可執行檔案

  • 啟動應用 這裡執行的編譯後的可執行檔案而不是 jar
cd target

./com.example.demo.demoapplication      
  • 啟動時間 0.215 seconds
2020-12-18 12:30:40.625  INFO 94578 --- [           main] com.example.demo.DemoApplication         : Started DemoApplication in 0.215 seconds (JVM running for 0.267)      
  • 看一下記憶體占用 24.8203MB
ps aux | grep com.example.demo.demoapplication | grep -v grep | awk '{print $11 "\t" $6/1024"MB" }'

./com.example.demo.demoapplication 24.8203MB      

資料對比

是否引入 GraalVM 記憶體占用 啟動時間
480.965MB 1135 ms
24.8203MB 215 ms

https://blog.didispace.com/spring-boot-2-4-feature-mem-95/#%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99 參考資料

[1] GraalVM:

https://www.graalvm.org

[2] Quarkus:

https://quarkus.io

[3] SDKMAN:

https://sdkman.io/install

[4] nvm:

https://github.com/creationix/nvm

[5] Gitee Gist:

https://gitee.com/gi2/codes/famcqz6n21iylpg3us7j036