[.NET大牛之路 005] .NET 的執行模型

精緻碼農發表於2021-08-09

.NET大牛之路 • 王亮@精緻碼農 • 2021.07.06

目錄:

前面我們介紹 .NET 歷史時講過,微軟基於 .NET Framework 重新設計並創造了跨平臺的 .NET Core,目前已經發展到 .NET 5 版本,它的效能較之前的 .NET Framework 有巨大的提升。而 .NET Framework 產品線也被宣告終止(微軟仍會繼續維護,只是不會再發布新版本),它的最後個版本 .NET Framework 4.8 成為了絕唱。

.NET Framework 終將成為歷史,我們要把思想從 .NET Framework 跳到 .NET Core/.NET 5+,首先要弄明白它們的執行模型和底層架構發生了什麼變化。

注:為了簡單起見,下文所說的 .NET Core 包含 .NET Core 和 .NET 5+。

我們先從一個高的角度來理解一下 .NET Core 執行模型的全貌,後面章節再從低的角度逐個拆開講解各個模組。

.NET Core 的執行模型有兩種,一種是基於 CoreCLR 執行時,這種和 .NET Framework 的執行模型幾乎一樣;另一種是基於 Native AOT 本地執行時,這是 .NET Core 新增的一種執行模型。

基於 CoreCLR

CoreCLR 和原來 .NET Framework 的 CLR(Common Language Runtime,公共語言執行時)幾乎是一樣的,只是 CoreCLR 去除了特定於 Windows 作業系統的部分,實現了跨平臺。所以除了 CLR 執行時有些不同之外,它們的執行模型是一樣的。

注意,平時我們會把 CoreCLR 習慣性地簡稱為 CLR,在 .NET Core 語境中,CLR 指的就是 CoreCLR。

基於 CoreCLR 的執行模型用簡單流程圖表示如下:

原始碼經過編譯器編譯,生成程式集,執行的時候,再由 CLR 針對不同的作業系統和 CUP 架構(如 x86、x64 或 ARM)把程式集編譯成原生程式碼(Native Code),原生程式碼可由作業系統直接執行。

注:在 .NET 中,原生程式碼就是機器碼(Machine Code),只是叫法不同。它是處理器能夠理解並直接執行的位元組碼指令。所有其他程式碼必須翻譯或轉換為機器碼才能在計算機上執行。

基於 Native AOT

.NET Core 基於 CoreCLR 提煉出了一個精簡版的本地執行時,移除了 JIT 編譯器,保留了垃圾回收器、記憶體管理等模組。這個本地執行時之前的代號叫 CoreRT ,現在叫 Native AOT

Native AOT 執行時提供了一套 AOT(Ahead Of Time) 提前編譯機制,它使用的是新一代的 RyuJIT 編譯器,可以將 .NET Core 程式編譯成原生程式碼(機器碼),可在宿主機器直接執行,不需要提前安裝 .NET Core 執行時。

基於 Native AOT 執行時的執行模型用簡單流程圖表示如下:

原始碼經過編譯器編譯,直接生成原生程式碼,釋出時將原生程式碼和本地執行時一起打包為單個可執行檔案,可直接在作業系統上執行。

要使用本地執行時,在 VS 中釋出時請選擇 Self-Contained 模式,同時需指定目標平臺及 CPU 架構(如win-x64linux-x65等)。由於打包的檔案包含本地執行時,所以它要比基於 CoreCLR 釋出的檔案要大幾十兆。

使用 Native AOT 本地執行時有兩大好處:一是釋出時只有一個檔案,已經包含本地執行時,不需要提前安裝執行時環境,可直接在宿主機上執行;二是啟動時本身就是機器嗎,不要經過 JIT 編譯器編譯,啟動效率更高。

小結

.NET Core 基於 CoreCLR 的執行模型和原來 .NET Framework 的執行模型是一樣的,沒有發生大的變化。另外,.NET Core 新增了一種基於 Native AOT 本地執行時的執行模型,它使用了 AOT 編譯機制,可直接把 .NET Core 程式編譯成機器碼。

希望大家根據文中的流程圖理解 .NET Core 兩個執行模型的全貌,並牢記。這有助於我們理解 .NET 程式的執行原理,也是面試的高頻話題。關於執行模型中的主要核心模組(編譯器、程式集和執行時),後面的章節再單獨詳細講解。

相關文章