首頁  >  文章  >  後端開發  >  詳細分析 .NET Core 構成體系(圖)

詳細分析 .NET Core 構成體系(圖)

黄舟
黄舟原創
2017-03-09 15:18:501756瀏覽

  前文介紹了.NET Core 在整個.NET 平台所處的地位,以及與.NET Framework的關係(原文鏈接),本文將詳細介紹.NET Core 框架的構成和各模組主要功能,以及如何實現跨平台。

詳細分析 .NET Core 構成體系(圖)

#   上圖描述了 .NET Core的系統組成,最上層是應用層,是開發基於UI應用的框架集,包括了ASP.NET Core(用於創建web app),和 UWP(用於創建Windows10 app)。

  中間層是公共庫(CoreFX),實現了.NET Standard Library ,囊括了常用系統級操作例如(文件、網絡等)。

在CoreFx下是運行時環境,.NET Core 包含了兩種運行時(CoreCLR、CoreRT),CoreCLR是一種基於即時編譯程序(Just in time compiler,JIT)的運行時,它使用了跨平台開源的編譯器RyuJIT,而CoreRT是使用提前編譯器(Ahead of time compiler,AOT)的運行時,它既可以使用RyuJIT來實現AOT編譯也可以使用其他的AOT編譯器。由於AOT提前編譯IL成了機器碼,在行動裝置上也具有更好的啟動速度和節能性。

最後也要提到一個開源的跨平台原始碼編譯器Roslyn,它有別於剛才兩個編譯器,JIT和AOT編譯器主要用於將IL編譯成本機機器碼,而Roslyn是將C# 或VB. NET 程式碼編譯成程式中間語言(intermediate language,IL)。

 Roslyn 編譯器

#   Roslyn編譯器用於將C#或VB.NET程式碼編譯為組件(assembly),它的編譯過程是一個管道式的處理過程總共包含4個步驟,具體過程見下圖。

compiler pipeline

#   A. Parser(解析)

  根據語法對原始程式碼進行解析。

  B. Declaration (宣告)

  為程式碼產生元資料(metadata),元資料是一個資料表的集合,描述了在目前程式碼中定義的資料型別和成員,同時也描述了所引用的型別及成員。

  C. Bind(綁定)

  將產生的IL程式碼與描述它的元資料綁定在一起,產生託管模組(managed module)。

  D. Emit(生成)

  將一個或多個託管模組合併生成組件(assembly)。

 RyuJIT 編譯器

#   在程式運作上需要執行某一個方法,首先需要將已經編譯好的IL轉換本機的機器碼,而這個任務就交給了RyuJIT。它是新一代JIT編譯器,第一次實現了AMD64的架構,RyuJIT能夠比JIT64(上一代編譯器)更快地產生程式碼,以提高程式運作效率。

 CoreCLR & CoreRT

# .NET Core Runtime (CoreCLR) 和.NET Core Runtime (CoreRT) 都是.NET Core的運行時(Runtime),它們提供了與.NET Framework CLR 類似的核心功能(內存管理、組件加載、安全性、例外、執行緒管理等),可由面向於執行時間的所有語言使用。

  CoreRT 和 CoreCLR 不同的是,CoreRT 提供了一套AOT 的機制,可以將.NET Core程式編譯成原生程式碼,不依賴 .NET 執行時間而運行在宿主機器上。除此之外兩個運行時大部分功能代碼是共享的,例如GC。 AOT的優化帶來不少好處:

  • 編譯後產生一個單一文件,包含所有的依賴,包括 CoreRT,無需安裝Framework

    #

  • # 啟動時是機器碼,不需要產生機器碼,也不要載入JIT編譯器

    #

  • # 可以使用其他最佳化編譯器,包括​​ LLILC ,IL to CPP

CoreRT有兩個方式產生機器碼,第一個使用是直接編譯IL成機器碼,預設情況下,RyuJIT 作為一個AOT 編譯器將IL編譯成機器碼,另一個方式是將C#程式碼編譯成C++程式碼,然後呼叫對應平台的C++編譯器優化編譯成機器碼。

  使用 RyuJIT 編譯成機器碼

dotnet restore
dotnet build --native --ilcpath <repo_root>\bin
\Product\Windows_NT.x64.Debug\packaging\publish1

  編譯產生 C++ 程式碼

dotnet restore
dotnet build --native --cpp --ilcpath <repo_root>\bin\Product\Windows_NT.x64.Debug\packaging\
publish1 --cppcompilerflags /MTd</repo_root>

  CoreRT也有不足之處,它需要為不同平台編譯一次;但凡事有但是,它允許工程師可以不發佈到不想支援的平台(例如某遊戲僅支援桌面,不支援手機)。

註:這兩個命名在.NET Core RC2 版本中都無法使用,按照官方說法是在當前版本中已經移除這個命令了,具體等6月27日正式版發出後才知道最後的情況

 CoreFX(.NET Core Libraries)

  CoreFX主要包含數個公共函式庫,例如 System.Collections, System.IO, System.Xml等。 CoreFX是 .NET Standard Library 的實現,同樣的.NET Framework 4.6.3也是基於.NET Standard Library的實作。它們目前都是基於.NET Standard Library1.6版本,具體見下表:

詳細分析 .NET Core 構成體系(圖)

#  .NET Core 程式碼開發、部署、執行流程

詳細分析 .NET Core 構成體系(圖)

#   從上圖可以看到使用JIT編譯和使用AOT編譯原始碼並執行程式是兩種不同的流程。

如果使用JIT編譯器部署程式時只需要將程式打包為IL的assemblies,在方法第一次執行前編譯器將IL編譯為目標機器機器碼(Native code),而AOT編譯會在編譯時將原始碼直接編譯為目標機器碼。

  AOT將原始碼編譯為機器碼,擁有以下特性:

  • # 用靜態程式碼取代反射,例如如果一個值型別(value type)沒有重寫ValueType.Equals 的equals的方法,預設情況判斷相等,會使用反射找到filedinfo以確定type是否相等,然後再比較value是否相等。而在AOT編譯中由於替換了反射因此只能比較value是否相等。

    #

  • # 依賴的第三方類別庫以及.NET Libraries都打包至最終編譯的程式中。

    #

  • # 打包後的程式運行在一個精簡版的運行時上(CoreRT)主要包含垃圾回收器,而運行時也會打包在app檔案中。

    #

  • # 雖然編譯時會取代反射程式碼,但遇動態反射程式碼無能為力,執行時期若遇動態反射呼叫則會因為找不到對應的元資料及實作而拋出例外。解決方法是編譯前配置執行時間指令檔(Runtime directive file)指定需要用到的組件。

    #

 總結

本節介紹了.NET Core的構成體系,包括新增的多個編譯器以及遵循.NET Standard Library的CoreFX,總體來說.NET Core較之前的.NET Framework 從性能和開發效率上都有很大的提升。關鍵是首次實現了.NET的完全跨平台能力的基礎技術堆疊。

  .NET Core 是基於跨平台能力,並沒有將與 GUI 高度相關的 API 移植到 .NET Core 內,因此像是 Windows Forms 或 Windows Presentation Foundation (WPF) 並未移植到 .NET Core。 .NET Core 支援控制台應用程式 (Console Application) 以及類別庫 (Class Library) 類型的專案。

  不過微軟在其 Universal Windows Platform (UWP) 開發平台使用了 .NET Core,並且利用 .NET Native 技術將其效能提升至十分接近原生碼的速度。

  ASP.NET Core 則以控制台應用程式驅動其託管環境 Kestrel Server 以支援 ASP.NET Core 程式的運作。

以上是詳細分析 .NET Core 構成體系(圖)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn