iT邦幫忙

2024 iThome 鐵人賽

DAY 8
0

在前一章節中,我們探討了 HotSpot JVM 及其核心的 JIT 編譯技術。HotSpot 透過「熱點」檢測和即時編譯,能夠在應用運行過程中不斷優化程式碼,從而在性能和資源使用之間取得平衡。然而,隨著現代應用場景的快速變化,特別是在 微服務 和 雲端原生應用 中,快速啟動和資源效率變得更加重要,這對傳統的 JIT 模式提出了挑戰。

為了解決這些需求,GraalVM 應運而生。作為對 HotSpot 的擴展,GraalVM 不僅延續了 JVM 的核心特性,還引入了更先進的 Ahead-of-Time (AOT) 編譯技術 和強大的多語言支持框架 Truffle,使得它能夠在各種應用場景中提供更快的啟動時間和更靈活的語言整合。

GraalVM:更快速、更靈活的 JVM 實現

下圖為架構示意, GraalVM基於 HotSpot 的擴展,它在保留 HotSpot 的優勢之外,通過兩個關鍵特性進一步提升性能:

  • Ahead-of-Time 編譯技術(AOT):取代了 HotSpot 中 JIT 編譯的部分,使應用程式在運行前就已經被編譯成了機器碼,顯著減少了啟動時間。
  • Language Implemenation Framework (Truffle 多語言支持框架):允許多種編程語言與 Java 一同在同一個虛擬機實例上運行,實現了跨語言的深度整合。

https://ithelp.ithome.com.tw/upload/images/20240909/20115895e5xGi0JgAp.png

GraalVM Complier

GraalVM Compiler 是一個高效的 動態即時編譯器 (JIT),由 Java 編寫,並與 HotSpot JVM 緊密集成。它通過 JVM Compiler Interface (JVMCI) 與 JVM 進行互動,可以動態將 Java 位元組轉換為高效的機器碼。以下是這三個技術在 GraalVM 編譯器中的具體角色:

  • Ahead-of-Time 編譯技術 (AOT)

    • AOT 編譯 是 GraalVM 的核心技術之一,它通過 Native Image 將 Java 及其他基於 JVM 的程式碼在運行之前直接編譯為本地機器碼。這樣編譯過後的應用可以獲得接近原生應用的性能,並且啟動速度極快,適合需要快速啟動和低資源占用的應用場景,如微服務和容器化應用。

    • GraalVM 編譯器 的 AOT 功能使應用在運行時不再依賴於 JVM 的即時編譯 (JIT),而是直接運行已經編譯好的本地程式碼,這大幅提升了應用的啟動速度和資源效率。

  • Partial Escape Analysis

    • Graal 編譯器中的一項動態優化技術,用來消除不必要的物件分配。當 GraalVM 編譯器判斷某個物件只在方法內部使用且不會『逸出』到方法外部時,它可以優化這些物件的分配,避免將它們分配到堆記憶體中,甚至完全消除這些分配。

    • GraalVM 編譯器 使用這項技術來減少垃圾回收的負擔,優化程式碼運行的記憶體管理,從而提升應用的整體運行效率。

  • Graph Compilation

    • 將不同程式語言的程式碼轉換為一種通用的中介表示(IR),即一種圖形化的程式碼結構。這讓 GraalVM 能夠對多種語言的程式碼(如 Java、JavaScript、Ruby、Python、R 等)進行統一的優化與編譯。簡單來說就是將程式碼的控制流程與數據流表示為一個圖形結構(通常是控制流程圖或數據流圖)。簡單來說就是利用圖形演算法(如圖的遍歷、縮減、優化路徑等)的技術來進行程式碼的優化與轉換

    • Graal 編譯器使用這個通用的圖形表示進行語言無關的優化,無論是哪種語言,編譯器都能在這個圖上進行優化與程式碼生成,從而實現高效的跨語言執行。

GraalVM vs Origin VM

簡易比較 傳統的 JVM (Origin VM) 和 GraalVM 中的編譯器架構如下圖(圖Source請點我)。GraalVM 中的 Graal 編譯器取代了傳統的 C2 編譯器,提供了先進的優化技術,特別是支持 AOT 和多語言協作,這是傳統 HotSpot JVM 所不具備的功能。另外引入了 JVMCI(JVM Compiler Interface),使得 Graal 編譯器可以更靈活地與 JVM 溝通,這也是 GraalVM 支持動態編譯和多語言運行的重要基礎。

| JVMCI允許 Graal 編譯器這類高階編譯器能夠與 JVM 互動,讀取位元碼、提取中繼資料,並將編譯後的機器碼注入 JVM 中。

https://ithelp.ithome.com.tw/upload/images/20240909/201158953RYuAqljhY.png

打包與部署流程不同

傳統 JVM 部署

流程如下
https://ithelp.ithome.com.tw/upload/images/20240909/20115895tQLMgGdd4z.png

Step1: 編譯:將應用程式碼經由 javac 編譯為位元碼(.class 檔案)。

Step2: 打包:使用 Buildpack 打包成一個可執行的 .jar 檔案,並將其放入容器中。

容器結構:容器內有三層:

  • 應用程式 (application.jar):打包好的 Spring Boot 應用。
  • JVM:運行應用程式所需的 Java 虛擬機(JVM)。
  • 作業系統:基礎的作業系統層,提供支援 JVM 與應用程式運行的基本服務。

在這種傳統方式下,應用啟動時間通常較長,因為它依賴 JVM 的即時編譯(Just-In-Time, JIT)來執行。

Ahead-of-Time (AOT) 編譯部署

流程如下
https://ithelp.ithome.com.tw/upload/images/20240909/201158951tLrqL1Fl3.png

Step1: AOT 優化:在程式編譯之前,先進行 Spring 的提前編譯(Ahead-of-Time, AOT)優化。

Step2 : 編譯:分為兩步:

  • Javac 編譯:將程式碼編譯成位元碼。
  • 原生映像編譯:將位元碼編譯成原生機器碼(Native Image),生成可直接執行的檔案。

Step3 : 打包:通過 Buildpack 打包,生成最小的應用可執行檔。

容器結構:容器內只有兩層:

  • 應用可執行檔:直接在硬體上執行的應用程式,不需要 JVM。
  • 最小化作業系統:為原生應用提供支援的最小作業系統。

AOT方式透過提前將應用程式編譯成原生機器碼,無需 JVM 即可運行,大幅減少了啟動時間和記憶體佔用,並生成更小、更高效的容器映像。

其他AOT編譯技術應用例子

  • C/C++ 語言:
    • 如 gcc 或 clang 等編譯器編譯C或C++程式時,所產生的就是直接為目標平台(例如:Linux、Windows)所編譯的機器碼。這就是AOT編譯的一個例子。
  • .NET Core:
    • NET Core提供了一個叫做crossgen的工具,可以將.NET的中間語言 (IL) 編譯成原生機器碼。這也是AOT的一種形式。

Truffle:多語言支持框架

Truffle 是 GraalVM 的一個多語言實作框架,它允許不同的程式語言在同一個執行環境中無縫協作。這樣的設計讓 GraalVM 不僅僅侷限於運行 Java 程式,而是能夠同時支援多種語言,包括 JavaScript、Ruby、Python、R 和 WebAssembly 等。這種跨語言執行的能力對於需要多語言協作的應用場景具有很大的價值。

優勢特性如下

  • 多語言相容性: Truffle 支援的不同語言可以在同一個 GraalVM 實例上共同運行,並且可以相互調用。這意味著開發者可以用不同語言編寫應用程式的不同部分,並實現深度整合。例如,開發者可以用 Java 撰寫伺服器端邏輯,用 JavaScript 或 Python 寫資料處理部分,所有這些程式碼都能在同一個虛擬機中協作運行。
  • 效能優化:透過 Truffle,GraalVM 能將多語言應用程式的執行邏輯編譯成高效的機器碼,並進行深度優化。即使是使用動態語言撰寫的程式,也能獲得接近靜態語言的效能,這對於過去因效能問題而受限的語言,如 Python 和 Ruby,尤其有幫助。
  • 跨語言工具支援:Truffle 允許開發者在不同語言間共享工具和函式庫,讓應用開發過程更加靈活。例如,Java 和 JavaScript 的除錯工具可以共享,語言間的程式碼自動完成、效能分析也可以互相支援。

Truffle命名 : 很奇特的命名…像松露一樣小小的有價值


上一篇
GraalVM快速理解-關於JVM
下一篇
Native Image
系列文
微服務奇兵:30天Quarkus特訓營13
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言