Spring Boot 3用CDS提升20%啟動時間

banq發表於2024-06-04

2024 年 5 月 23 日,Spring Boot 團隊釋出了3.3.0版本:“CDS 支援改善啟動時間並減少記憶體消耗。”

在本文中,我們將建立一個名為GreetingsApp的簡單 Java Web Spring Boot應用程式。然後,我們將比較標準 Uber JAR 和在 jarmode 的幫助下提取 Uber JAR 建立的 CDS 友好佈局中的 JAR 的啟動時間和記憶體佔用。

什麼是類資料共享 (CDS)
類資料共享 (CDS)是 Java 虛擬機器 (JVM) 中的一項功能,可幫助縮短啟動時間並減少 Java 應用程式的記憶體佔用。

CDS 的工作原理是:

  • 建立一個包含標準 Java 庫中的類的共享存檔檔案。
  • 當應用程式啟動時,JVM 可以從共享存檔中載入這些類,而不是單獨載入它們。

這不僅可以加快啟動過程,還可以允許多個 JVM 例項在記憶體中共享相同的類資料,從而減少總體記憶體使用量。

先決條件
如果您想繼續,您的機器上必須安裝Java 17+和Docker 。

建立 Spring Boot 應用程式
讓我們使用Spring Initializr建立一個 Spring Boot 應用程式。
應用程式名稱將是GreetingsApp,唯一的依賴項是Spring Web。

我們將使用 Spring Boot 版本3.3.0和 Java 17。

建立 GreetingsController 類

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(<font>"/greetings")
public class GreetingsController {
    
    @GetMapping
    public String greeting(@RequestParam(required = false) String name) {
        return
"Hello %s!".formatted(name == null ? "World" : name);
    }
}


這個 Java 類處理 GET 請求,/greetings如果提供了引數則返回“Hello [name]!” name,如果沒有提供則返回“Hello World!”。

建立 MemoryUsageLogger 類
在com.example.GreetingsApp包中,讓我們建立MemoryUsageLogger具有以下內容的類:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

@Component
public class MemoryUsageLogger implements ApplicationRunner {

    private static final Logger logger = LoggerFactory.getLogger(MemoryUsageLogger.class);

    @Override
    public void run(ApplicationArguments args) {
        Runtime runtime = Runtime.getRuntime();
        long memoryUsedBytes = runtime.totalMemory() - runtime.freeMemory();
        long memoryUsedMB = memoryUsedBytes / (1024 * 1024);
        logger.info(<font>"Memory footprint at startup: {} MB", memoryUsedMB);
    }
}

此 Java 類記錄啟動時的記憶體使用情況。當應用程式啟動時,它會計算已用記憶體並使用 SLF4J 記錄。

生成 Uber JAR
在終端和 GreetingsApp 根資料夾中,執行以下命令來打包 Uber JAR:

./mvnw clean package -DskipTests

該GreetingsApp-0.0.1-SNAPSHOT.jar檔案將在目標中生成folder。

生成 CDS 友好佈局
在終端和 GreetingsApp 根資料夾中,執行以下命令來生成 CDS 友好佈局:

java -Djarmode=tools -jar target/GreetingsApp-0.0.1-SNAPSHOT.jar extract

將會建立一個名為的資料夾GreetingsApp-0.0.1-SNAPSHOT。其中,我們將包含GreetingsApp-0.0.1-SNAPSHOT.jar檔案(我們將其稱為CDS JAR)和lib包含所有所需庫的資料夾。

啟動 5 次 Uber JAR
在終端的 GreetingsApp 根資料夾中,執行以下命令來啟動該應用程式。按Ctrl+C關閉它,並重復此過程五次:
java -jar target/GreetingsApp-0.0.1-SNAPSHOT.jar

以下是我們進行的 5 次執行的結果(為簡潔起見,省略了一些日誌行):


:: Spring Boot :: (v3.3.0) 
... 
2024-05-26T10:37:22.651+02:00 INFO 99104 --- [GreetingsApp] [ main] ceGGreetingsAppApplication :在 2.401 秒內啟動 GreetingsAppApplication(程序執行 2.984 秒)
2024-05-26T10:37:22.655+02:00 INFO 99104 --- [GreetingsApp] [ main] ceGreetingsApp.MemoryUsageLogger :啟動時的記憶體佔用:14 MB
 ^C% 


在 CDS 友好佈局中啟動 5x JAR
在終端的 GreetingsApp 根資料夾中,執行以下命令來啟動該應用程式。按Ctrl+C關閉它,並重復此過程五次:

java -jar GreetingsApp-0.0.1-SNAPSHOT/GreetingsApp-0.0.1-SNAPSHOT.jar

以下是我們進行的 5 次執行的結果(為簡潔起見,省略了一些日誌行):


:: Spring Boot :: (v3.3.0) 
... 
2024-05-26T10:41:57.459+02:00 INFO 99303 --- [GreetingsApp] [ main] ceGGreetingsAppApplication : 在 1.947 秒內啟動 GreetingsAppApplication(程序執行了 2.275 秒)
2024-05-26T10:41:57.462+02:00 INFO 99303 --- [GreetingsApp] [ main] ceGreetingsApp.MemoryUsageLogger : 啟動時的記憶體佔用:18 MB
 ^C% 


比較:Uber JAR 與 CDS JAR
下表顯示了上述執行獲得的啟動時間和記憶體佔用:
JAR 型別|啟動時間(秒) |啟動時的記憶體佔用(MB) | 

-------- + ------------------- + -------------------------------- | 
Uber JAR | 2.369 | 19 | 
Uber JAR | 2.389 | 19 | 
Uber JAR | 2.359 | 33 | 
Uber JAR | 2.401 | 14 | 
Uber JAR | 2.425 | 19 | 
........ + ................... + ................................ | 
CDS JAR | 1.947 | 18 | 
CDS JAR | 2.032 | 14 | 
CDS JAR | 1.953 | 16 | 
CDS JAR | 1.908 | 17 | 
CDS JAR | 1.940 | 18 |

平均值為:
JAR 型別|平均啟動時間(秒) |啟動時平均記憶體佔用(MB) | 

-------- + ----------------------- + ------------------------------------ | 
Uber JAR | 2.388 | 20.8 | 
........ + ......................... + .................................... | 
CDS JAR | 1.956 | 16.6 |

從平均值表中我們可以看出:

  • CDS JAR 的啟動時間比 Uber JAR 快約18.09%
  • 此外,記憶體佔用也減少了約20.19%。

結論
在本文中,我們建立了一個名為 GreetingsApp 的簡單 Java Web Spring Boot 應用程式,以探索類資料共享 (CDS) 的好處。透過比較標準 Uber JAR 與 CDS JAR 的啟動時間和記憶體佔用,我們展示了 CDS 如何增強 Java 應用程式。結果表明,使用 CDS 可顯著縮短啟動時間和減少記憶體佔用,縮短約 20%,使其成為最佳化 Java 應用程式的寶貴功能。

Java 有一些改進,特別是GraalVM和CRaC。在 CDS、GraalVM 和 CRaC 之間做出選擇時,重要的是要考慮它們的準備情況和易用性。雖然 GraalVM 和本機構建很有前景,但它們可能尚未完全準備好用於生產。另一方面,CDS 已經成熟且易於實現,使其成為最佳化 Java 應用程式的啟動時間和記憶體使用情況的可靠選擇。

相關文章