NET Core 3.0 正式公布:新特性詳細解讀

2019-09-30

作者丨Richard Lander   譯者丨核子可樂    策劃丨趙钰瑩

近日,.NET Core 3.0 正式發(fā)布。此次新版本包含一系列重要改進(jìn),添加了 Windows Forms 與 WPF、添加新的 JSON API、對(duì) ARM64 的支持能(néng)力以及全面(miàn)提高的性能(néng)水平等。此外,C# 8 也是此次新版本的重要組成(chéng)部分,其中包含可空、異步流以及更多模式。F# 4.7 則專注于放寬語法限制,并專門匹配 .NET Standard 2.0。開(kāi)發(fā)者現在可以立即將(jiāng)原有項目更新爲 .NET Core 3.0,此次新版本與原有版本兼容,大家可以放心體驗。

QQ圖片20190930112954.png

根據微軟博客的介紹,開(kāi)發(fā)者可以面(miàn)向(xiàng) Windows、MacOS 以及 Linux 等系統平台下載 .NET Core 3.0 :

.NET Core 3.0 SDK 與運行時

Snap 安裝程序

Docker 鏡像

此外, ASP .NET Core 3.0 與 EF Core 3.0 也已經(jīng)一同發(fā)布。Visual Studio 2019 16.3 與 Visual Studio for Mac 8.3 亦同時發(fā)布,且需要更新才能(néng)确保 .NET Core 3.0 與 Visual Studio 的協同使用。.NET Core 3.0 爲 Visual Studio 2019 16.3 中的組成(chéng)部分,開(kāi)發(fā)者可以選擇直接升級至 Visual Studio 2019 16.3,從而立刻獲取 .NET Core。

感謝所有爲 .NET Core 3.0 做出貢獻的朋友們!此次最新版本的發(fā)布源自數百位團隊成(chéng)員的努力,也包括技術社區的重大貢獻。

發(fā)行說明:

.NET Core 3.0 發(fā)行說明

.NET Core 2.2 -> 3.0 API 的區别

.NET Core 3.0 貢獻者名單

GitHub 發(fā)行版

關于 .NET Core 3.0 的 GitHub 問題解答

1

3.0 版本,開(kāi)發(fā)者需要了解什麼(me)?

在深入探究 .NET Core 3.0 中的全部新功能(néng)之前,我們首先需要強調幾項關鍵性的改進(jìn)與指導内容。以下是整理出的要點清單:

.NET Core 3.0 已經(jīng)在 dot.net 以及 Bing.com 上托管了幾個月,通過(guò)了一系列嚴苛的測試。衆多其他微軟團隊也將(jiāng)很快在生産流程當中通過(guò) .NET Core 3.0 部署一系列大型工作負載。

多種(zhǒng)組件的性能(néng)得到顯著提升,感興趣的朋友可以點擊此處參閱 .NET Core 3.0 的性能(néng)改進(jìn)說明。

C# 8 加入了異步流、範圍 / 索引、更多模式以及可爲空的引用類型。可爲空意味着可以直接發(fā)現那些導緻 NullReferenceException 問題的代碼缺陷。框架庫的最底層注釋也已添加完成(chéng),以幫助了解何時爲 Null。

F# 4.7 緻力于通過(guò)隐式 yield 表達式及相關語法降低某些操作的實現難度。其中還(hái)包含對(duì) LangVersion 的支持,提供 nameof 并可以預覽形式打開(kāi)靜态類。F# Core 核心庫現在還(hái)與 .NET Standard 2.0 相匹配。您可以點擊此處參閱 F# 4.7 發(fā)布公告中的細節信息。

.NET Standard 2.1 增加了可與 .NET Core 以及 Xamarin 共同使用的代碼類型集。.NET Standar 2.1 當中包含 .NET Core 2.1 以及之後(hòu)版本中的所有類型。

Windows 桌面(miàn)應用現已面(miàn)向(xiàng) Windows Forms 與 WPF(開(kāi)源)得到 .NET Core 支持。其中,WPF 設計器爲 Visual Studio 2019 16.3 版本中的組成(chéng)部分。Windows Forms 設計器仍處于預覽狀态,并可通過(guò) VSIX 下載的形式獲取。

.NET Core 應用現在默認具備可執行文件。在以往的發(fā)行版中,應用需要通過(guò) dotnet 命令方啓動,例如 dotnet myapp.dll。現在,可以通過(guò)應用特定可執行文件實現應用啓動,例如 myapp 或者./myapp,具體視使用的操作系統而定。

高性能(néng) JSON API 加入新版本,适用于 reader/writer、對(duì)象模型以及序列化場景等。這(zhè)些 API 在 Span 基礎之上重新構建而成(chéng),且在底層使用 UTF8(而非 string 等 UTF16)。這(zhè)些 API 能(néng)夠將(jiāng)分配需求控制在最低程度,從而提高性能(néng)、減少垃圾收集器的工作量。具體請參閱.NET Core 3.0 中的 JSON 未來發(fā)展說明。

默認情況下,垃圾收集器的内存占用量得到了顯著削減。對(duì)于將(jiāng)衆多應用程序托管在同一服務器之上的使用場景,這(zhè)項改進(jìn)可謂意義重大。垃圾收集器本身也得到了更新,能(néng)夠利用 64 核及以上設備的大量計算核心。

.NET Core 已針對(duì) Docker 進(jìn)行了增強,以使 .NET 應用程序能(néng)夠在容器中以可預測的方式高效運作。在容器配置中的内存或 CPU 資源有限時,目前的垃圾收集器與線程池更新結果也能(néng)帶來更好(hǎo)的運作效果。.NET Core docker 鏡像也變得更小,其中 SDK 鏡像的瘦身效果尤其明顯。

Raspberry Pi 與 ARM 芯片現已得到支持,可配合遠程 Visual Studio 調試程序等工具實現物聯網開(kāi)發(fā)。開(kāi)發(fā)者可部署應用以監聽各傳感器,同時將(jiāng)消息或者圖像輸出至顯示器上,整個過(guò)程皆可通過(guò)新的 GPIO API 實現。ASP.NET 則可用于將(jiāng)數據公布于 API 或者以站點的形式對(duì)物網設備進(jìn)行配置。

.NET Core 3.0 即爲“當前”版本,我們計劃在 2019 年 11 月推出下一代 .NET Core 3.1 版本。.NET Core 3.1 將(jiāng)爲長(cháng)期支持(LTS)版本(周期至少爲 3 年)。我們建議您首先采用 .NET Core 3.0,而後(hòu)更新至 3.1 版,升級過(guò)程將(jiāng)非常輕松。

.NET Core 2.2 將(jiāng)于今年 12 月 23 日停止服務,具體情況請參閱 .NET Core 支持策略。

.NET Core 3.0 將(jiāng)通過(guò) RHEL 8 的紅帽 Applicaltion Streams 交付,這(zhè)也是我們與紅帽公司多年合作的最新成(chéng)果。

對(duì)于希望在 Windows 上使用 .NET Core 3.0 的用戶,將(jiāng)必須升級至 Visual Studio 2019 16.3。

對(duì)于希望在 Mac 上使用 .NET Core 3.0 的用戶,將(jiāng)必須升級至 Visual Studio for Mac 8.3。

Visual Studio Code 用戶應始終使用最新版本的 C# 擴展,以确保能(néng)夠正常支持最新方案,包括與 .NET Core 3.0 的匹配。

.NET Core 3.0 的 Azure App Serivce 部署目前正在進(jìn)行當中。

.NET Core 3.0 的 Azure Dev Ops 部署即將(jiāng)推出。我們將(jiāng)在準備就緒之後(hòu)發(fā)布更新。

平台支持

.NET Core 3.0 將(jiāng)在以下操作系統平台上得到支持:

Alpine: 3.9+

Debian: 9+

openSUSE: 42.3+

Fedora: 26+

Ubuntu: 16.04+

RHEL: 6+

SLES: 12+

macOS: 10.13+

Windows Client: 7, 8.1, 10 (1607+)

Windows Server: 2012 R2 SP1+

備注:Windows Forms 與 WPF 應用隻适用于 Windows 操作系統。

芯片支持情況:

x64,Windows、macOS 以及 Linux

x86,Windows

ARM32,Windows 與 Linux

ARM64,Linux (kernel 4.14+)

備注:請确保 .NET Core 3.0 ARM64 部署方案采用 Linux 内核 4.14 或者更新版本。例如,Ubuntu 18.04 能(néng)夠滿足這(zhè)一條件,但 16.04 版本無法支持。

WPF 與 Windows Forms

開(kāi)發(fā)者可以在 Windows 系統上利用 .NET Core 3 構建 WPF 與 Windows Forms 應用從項目起(qǐ)步之初,我們就制定了強大的兼容性目标,旨在保證桌面(miàn)應用程序能(néng)夠從 .NET Framework 輕松遷移至 .NET Core 當中。我們已經(jīng)收到衆多開(kāi)發(fā)人員的反饋,了解到他們已經(jīng)成(chéng)功將(jiāng)自己的應用遷移至 .NET Core 3.0,且整個流程非常輕松便捷。從了盡可能(néng)降低對(duì)開(kāi)發(fā)人員的影響,WPF 以及 Windows Forms 沒(méi)有受到任何影響,其仍可在 .NET Core 上正常運行。事(shì)實上,項目本身進(jìn)行了重大調整,但我們認爲不對(duì)用戶造成(chéng)影響才是最好(hǎo)的調整方式。

下圖所示爲一款 .NET Core Windows Forms 應用:

QQ圖片20190930113120.png


Visual Studio 2019 16.3 已經(jīng)支持創建能(néng)夠匹配 .NET Core 的 WPF 應用。其中包括新的模闆、經(jīng)過(guò)更新的 XAML 設計器以及 XMAL Hot Reload。該設計器類似于現有 XAML 設計器(能(néng)夠匹配.NET Framework),但二者在體驗上仍然略有不同。

從技術層面(miàn)來看,最大的區别在于面(miàn)向(xiàng) .NET Core 的設計器采用新的接口進(jìn)程(wpfsurface.exe)以僅運行針對(duì) .NET Core 版本的運行時代碼。以往,.NET Framework WPF 設計器進(jìn)程(xdesproc.exe)本身即爲承載設計器的 WPF .NET Framework 進(jìn)程;由于運行時不兼容,我們無法使用 WPF .NET Framework 進(jìn)程(在本示例爲中 Visual Studio)將(jiāng)兩(liǎng)個版本的 .NET(即 .NET Framework 與 .NET Core)加載至同一進(jìn)程當中。這(zhè)意味着設計器在一定程度上(例如設計器擴展)無法以同樣的方式運作。如果正在編寫設計器擴展,我們建議認真閱讀 XAML 設計器擴展遷移文檔。

下圖所示爲顯示在新設計器當中的 WPF 應用:

微信圖片_20190930113238.png


Windows Forms 設計器目前仍處于預覽狀态,可以單獨進(jìn)行下載。其將(jiāng)在後(hòu)續更高版本内被添加至 Visual Studio 當中。該設計器的當前預算版包含對(duì)最常用控件以及底層功能(néng)的支持。我們將(jiāng)通過(guò)每月更新不斷對(duì)該設計器做出更新。我們目前不建議大家將(jiāng)自己的 Windows Forms 應用程序移植至 .NET Core,特别是在高度依賴設計器的情況下。希望開(kāi)發(fā)者體驗目前的設計器預覽版,并積極向(xiàng)我們反饋問題。

另外,大家也可以利用 .NET CLI 通過(guò)命令行進(jìn)行桌面(miàn)應用程序的創建與構建。例如,您可以通過(guò)以下命令快速創建一個新的 Windows Forms 應用:

您也可以利用同樣的流程創建 WPF 應用:

早在 2018 年 12 月,我們就將(jiāng) Windows Forms 與 WPF 轉化爲開(kāi)源項目。很高興看到,目前技術社區以及 Windows Forms 及 WPF 團隊正共同努力以改進(jìn)這(zhè)兩(liǎng)套 UI 框架。在 WPF 方面(miàn),我們最初在 GitHub 庫中隻擁有少量代碼,但目前幾乎全部 WPF 代碼都(dōu)已經(jīng)發(fā)布至 GitHub。随着時間的推移,未來還(hái)將(jiāng)有更多組件出現。與其他 .NET Core 項目一樣,這(zhè)些新的庫將(jiāng)成(chéng)爲 .NET Foundation 的一部分,并遵循 MIT 開(kāi)源許可。

System.Windows.Forms.DataVisualization 軟件包(包含圖表控件)目前也适用于新的 .NET Core 版本。大家現在可以將(jiāng)這(zhè)些控制添加到您的 .NET Core WinForms 應用程序當中。該圖表控件的源代碼可從 Github 上的 dotnet/winforms-datavisualization 處獲取。控件本身已經(jīng)進(jìn)行了調整,以簡化面(miàn)向(xiàng) .NET Core 3 的移植過(guò)程,但我們并不打算對(duì)其做出大規模更新。

Windows 原生互操作

Windows 以常規 API、COM 以及 WinRT 的形式提供豐富的原生 API。我們也從 .NET Core 1.0 時代起(qǐ)即提供對(duì) P/Invoke 的支持;在此次 .NET Core 3.0 當中,我們進(jìn)一步添加了 CoCreate COM API、主動 WinRT API,以及將(jiāng)托管代碼以 COM 組件形式處理等功能(néng)。很多開(kāi)發(fā)人員都(dōu)就這(zhè)些功能(néng)向(xiàng)我們提出申請,我們相信其正式推出也將(jiāng)給大家的日常工作帶來巨大便利。

去年下半年,我們宣布已經(jīng)設法通過(guò) .NET Core 實現了 Excel 自動化。那絕對(duì)是個有趣的時刻。在底層,我們的展示利用到 COM 互操作機制,例如 NOPIA、對(duì)象等效性以及自定義編組器等等。現在,您可以在擴展示例當中親自體驗多種(zhǒng)相關演示方案。

目前,.NET Core 3.0 隻部分支持托管 C++ 與 WinRT 互操作,完整的支持能(néng)力將(jiāng)在 .NET Core 3.1 當中推出。

可空引用類型

C# 8.0 當中引入了可空與不可空兩(liǎng)種(zhǒng)新的引用類型,這(zhè)意味着用戶可以對(duì)引用類型變量的屬性做出重要聲明:

某項引用不應爲空。當變量不應爲空時,則編譯器會強制執行規則以确保安全地撤銷針對(duì)空變量的引用,而無需預先檢查引用目标是否爲空。

某項引用可以爲空。當變量可以爲空時,編譯器會強制執行規則以确保您已經(jīng)對(duì)所引用的變量是否爲空做出檢查。

相較于無法從引用變量的變量聲明當中确定設計意圖的早期 C# 版本,此次發(fā)布的新功能(néng)具有明顯的優勢。通過(guò)添加可空這(zhè)一全新引用類型,您將(jiāng)能(néng)夠更明确地聲明自己的設計意圖,而編譯器則可以幫助您正确地完成(chéng)這(zhè)一目标并及時發(fā)現代碼中的錯誤。

接口成(chéng)員的默認實現

目前,一旦接口發(fā)布完畢,您將(jiāng)無法對(duì)其做出任何變更:換言之,要向(xiàng)其中添加新成(chéng)員,我們就必然會對(duì)現有界面(miàn)的實現成(chéng)員造成(chéng)破壞。

在 C# 8.0 當中,大家可以爲某一接口成(chéng)員提供主體。結果就是,如果實現該接口的類沒(méi)有實現該成(chéng)員(可能(néng)是因爲編寫代碼時還(hái)不存在該成(chéng)員),那麼(me)調用代碼將(jiāng)隻能(néng)獲得默認的實現效果。

在本示例當中,ConsoleLogger 類并不需要實現對(duì) ILogger 中的 Log(Exception) 重載,因爲其是通過(guò)默認實現進(jìn)行聲明的。現在,隻要爲現有實現成(chéng)員提供默認實現,您就可以随時向(xiàng)現有接口添加新的成(chéng)員。

異步流

現在,您可以利用 IAsyncEnumerable 對(duì)異步數據流進(jìn)行 foreach。這(zhè)一新的接口滿足了衆多開(kāi)發(fā)人員的長(cháng)久需求,也就是 IEnumerable 的異步版本。該語言允許大家對(duì)任務進(jìn)行 await foreach 以使用其元素。在産生方面(miàn),您的 yield return 條目可能(néng)會産生異步流。雖然聽起(qǐ)來似乎比較複雜,但其實際上將(jiāng)在實踐當中顯著簡化操作。

以下示例展示了異步流的産生與使用情況。其中的 foreach 聲明爲異步,其本身會利用 yield return 爲調用程序産生一條異步流。這(zhè)種(zhǒng)利用 yield return 的模式亦是我們推出的異步流标準生産方式。

除了能(néng)夠實現 await foreach 之外,大家也可以創建出異步叠代器,例如一個能(néng)夠返回 IAsyncEnumerable/IAsyncEnumerator 并在其中同時實現 await 與 yield return 的叠代器。對(duì)于需要處理的對(duì)象,您也可以使用能(néng)夠實現 Stream 以及 Timer 等多種(zhǒng)框架類型的 IAsyncDisposable。

索引與範圍

我們還(hái)創建了新的語法與類型,可用于描述索引器、數組元素訪問或者可以直接進(jìn)行數據訪問的任何其他類型。其中包括對(duì)單一值(索引的通常定義)或者兩(liǎng)個值(描述範圍)的支持。

Index 是一種(zhǒng)用于描述數組索引的新類型。您可以從通過(guò) int 從零開(kāi)始對(duì) Index 進(jìn)行計數,也可以使用 ^ 前綴運算符創建索引。在以下示例中,我們可以同時觀察到這(zhè)兩(liǎng)種(zhǒng)情況:

Range 的概念基本相同,其由兩(liǎng)個 Index 值構成(chéng),其一代表開(kāi)始、其二代表結束,且可以用 x…y 的範圍表達式編寫。接下來,大家即可使用 Range 索引以生成(chéng)底層數據的一個切片,具體如下所示:

使用聲明很多朋友可能(néng)已經(jīng)厭倦了使用那些要求縮進(jìn)代碼的語句,對(duì)吧?沒(méi)問題,現在不會了。您可以按以下形式編寫代碼,該代碼將(jiāng)在當前語句塊的作用域末尾添加 using 聲明,而後(hòu)將(jiāng)對(duì)象放置在其末尾。

Switch 表達式

幾乎每一位 C# 用戶都(dōu)非常喜歡 switch 語句的概念,但卻不太喜歡它的語法。C# 8 引入了 switch 表達式,該表達式可實現以下功能(néng):

terser 語法

由于其屬于表達式,所以會返回一個值

與模式匹配全面(miàn)集成(chéng)

Switch 表達式中的關鍵字爲“infix”,意味着該關鍵字位于測試值(在第一個示例中爲 0)與示例列表之間,這(zhè)種(zhǒng)形式與 Lambda 表達式非常相似。

第一個示例對(duì)各方法使用了 Lambda 語法,該語法能(néng)夠與 switch 表達式良好(hǎo)集成(chéng),但并非必需。

在此示例中,共有兩(liǎng)種(zhǒng)模式在發(fā)揮作用。首先,0 會與 Point 類型模式匹配,而後(hòu)再與内的屬性模式匹配。_ 用于描述丢棄模式,其與 switch 語句的默認模式想再。

大家也可以更進(jìn)一步依賴元組解構與參數位置,具體如下所示:

在本示例中,大家可以看到我們并不需要爲每一種(zhǒng)情況定義變量或者顯式類型。相反,編譯器可以將(jiāng)當前正在測試的元組與已經(jīng)定義的元組進(jìn)行匹配。

所有這(zhè)些模式,使得我們能(néng)夠編寫出意圖更加明确的聲明性代碼,而非單純執行測試的過(guò)程代碼。編譯器能(néng)夠負責實現無聊的過(guò)程代碼,并保證其始終得到正确執行。

當然,在某些情況下,switch 語句的實際效果可能(néng)仍然優于新的 switch 表達式與模式中的語法形式。

速度更快的 JSON API

.NET Core 3.0 當中包含一個新的 JSON API 家族,其用于實現 reader/writer 場景、利用文檔對(duì)象模型(DOM)實現随機訪問外加一個序列化程序。大家可能(néng)已經(jīng)非常熟悉如何使用 Json.NET 。新的 API 旨在滿足大多數同類場景需求,但内存需求更低、執行速度更快。

簡而言之,我們希望構建一個新的 JSON API,從而充分利用.NET Core 中的所有全新性能(néng)優勢,并以此爲基礎全面(miàn)提升性能(néng)水平。很明顯,我們不可能(néng)在保持現有代碼庫(例如 Jason.NET )兼容性的同時達成(chéng)這(zhè)一目标。

下面(miàn),讓我們分層對(duì)這(zhè)一新的 API 家族做出闡述。

Utf8JsonReader

System.Text.Json.Utf8JsonReader 是種(zhǒng)面(miàn)向(xiàng)面(miàn)向(xiàng) UTF-8 編碼 JSON 文本的高性能(néng)、低分配、純轉發(fā)讀取器,負責從 ReadOnlySpan 當中讀取内容。Utf8JsonReader 是一種(zhǒng)基礎的低級類型,我們可以利用它構建自定義解析器與解串器。利用新的 Utf8JasonReader,對(duì) JSON 負載的讀取速度將(jiāng)可達到以往 Json.NET 中讀取速度的兩(liǎng)倍。另外,除非大家需要將(jiāng) JSON 令牌實現爲(UTF16)字符串,否則其不會進(jìn)行分配。

Utf8JsonWriter

System.Text.Json.Utf8JsonWriter 提供一種(zhǒng)高性能(néng)、非緩存、純轉發(fā)方式,可用于將(jiāng) String、Int32 以及 DateTime 等常規.NET 類型寫入爲 UTF-8 編碼 JSON 文本。與 reader 類似,writer 是一種(zhǒng)基礎低級類型,開(kāi)發(fā)人員可以利用它構建自定義序列化程序。使用新的 Utf8JasonWriter,JSON 負載的編寫速度將(jiāng)比 Json.NET 寫入器高 30% 到 80%,且不進(jìn)行分配。

JsonDocument

System.Text.Json.JsonDocument 能(néng)夠對(duì) JSON 數據進(jìn)行解析,并建立隻讀文檔對(duì)象模型(DOM)功能(néng),用以查詢該對(duì)象以支持随機訪問與枚舉。其建立在 Utf8JasonReader 基礎之上,組成(chéng)數據的 JSON 元素可以通過(guò)由 JsonDocument 類型(被稱爲 RootElement 屬性)公開(kāi)的 JsonElement 類型進(jìn)行訪問。JsonElement 當中包含 JSON 數組與對(duì)象枚舉器,外加用于將(jiāng) JSON 文本轉換爲常見.NET 類型的 API。利用 JsonDocument,對(duì)常規 JSON 負載進(jìn)行解析并訪問其中各成(chéng)員的速度,一般可以達到以往 Json.NET 的 2 到 3 倍;而且由于數據本身大小合理(小于 1 MB),因此幾乎不需要進(jìn)行數據分配。

JSON 序列化器

System.Text.Json.JsonSerializer 層位于高性能(néng) Utf8JsonReader 與 Utf8JsonWriter 之上。其負責對(duì)來自 JSON 的對(duì)象進(jìn)行反序列化,并對(duì)指向(xiàng) JSON 的對(duì)象進(jìn)行序列化。内存分配得到嚴格控制,同時支持利用 Stream 以異步方式進(jìn)行 JSON 讀取與寫入。

引入全新 SqlClient

SqlClient 是一款數據提供程序,您可以利用它直接利用 ADO .NET API 訪問微軟 SQL Server 以及 Azure SQL Database 等。SqlClient 已經(jīng)正式發(fā)布,并通過(guò) Microsoft.Data.SqlClient NuGet 工具包進(jìn)行更新,且同時支持 .NET Freamework 與 .Net Core 應用程序。通過(guò)使用 NuGet,SQL 團隊將(jiāng)能(néng)夠更輕松地爲 Freamework 與 .Net Core 用戶提供更新。

ARM 與物聯網支持

我們在本次發(fā)行版當中實現了對(duì) Linux ARM64 的支持,這(zhè)也是對(duì)此前 .NET Core 2.1 與 2.2 版本當中面(miàn)向(xiàng) Linux 與 Windows 提供 ARM32 支持能(néng)力的延續。雖然某些物聯網工作負載能(néng)夠發(fā)揮我們現有 x64 功能(néng)提供的優勢,但仍有不少用戶強烈要求發(fā)布 ARM 支持功能(néng)。現在這(zhè)一功能(néng)已經(jīng)落實到位,我們也在與計劃進(jìn)行大規模部署的客戶開(kāi)展廣泛合作。

不少利用.NET 的物聯網部署場景涉及邊緣設備,且完全面(miàn)向(xiàng)網絡。其他一些場景則要求對(duì)硬件進(jìn)行直接訪問。在本次發(fā)行版中,我們添加了新的功能(néng)以在 Linux 上使用串行端口,同時可利用 Raspberry Pi 等設備上的數字引腳功能(néng)。該引腳使用多項協議。我們還(hái)添加了對(duì) GPIO、PWM、I2C 以及 SPI 的支持,以支持讀取傳感器數據、以無線方式交互并將(jiāng)文本與圖像輸出至顯示器等功能(néng)。

此功能(néng)屬于以下軟件包中的組成(chéng)部分:

System.Device.Gpio

Iot.Device.Bindings

作爲 GPIO(及其他同類協議)支持的一部分,我們審視了以往版本中的原有元素。我們發(fā)現其中的 C# 與 Python API,在這(zhè)兩(liǎng)種(zhǒng)場景下 API 都(dōu)屬于原生庫上的打包器,而這(zhè)些庫則采用 GPL 許可。我們認爲這(zhè)種(zhǒng)方法缺乏可持續性。因此,我們構建了 100% 純 C# 解決方案以實現這(zhè)些協議,這(zhè)意味着我們的 API 可以在支持 .NET Core 的任何環境下運作,利用 C# 調試器(通過(guò) sourcelink)進(jìn)行調試,并支持多種(zhǒng)底層 Linux 驅動程序(包括 sysfs、libgpoid 以及其它針對(duì)特定主闆的驅動程序)。所有代碼皆遵循 MIT 許可。與現有技術相比,我們認爲這(zhè)種(zhǒng)新方法將(jiāng)給.NET 開(kāi)發(fā)人員帶來巨大的便利。

.NET Core 運行時前滾策略更新

現在,.NET Core 運行時(更具體地講,運行時綁定程序)開(kāi)始提供主版本的前滾選擇策略。運行時綁定程序將(jiāng)默認啓用面(miàn)向(xiàng)補丁與次版本的前滾功能(néng)。我們決定公開(kāi)一組更爲廣泛的策略,以幫助開(kāi)發(fā)人員快速恢複可能(néng)存在的更新問題,但原有前滾操作并不受影響。

我們發(fā)布了一項名爲 RollForward 的新屬性,該屬性能(néng)夠接受以下值:

LatestPatch——前滾至最新補丁版本。其會禁用 Minor 策略。

Minor ——前滾至最早次版本以解決所需次版本缺失問題。如果該次版本存在,則 LatesPatch 策略即可起(qǐ)效。這(zhè)也是系統中采用的默認策略。

Major ——前滾至最早主版本與最早次版本,以解決所需主版本缺失問題。如果該主版本存在,則随後(hòu)使用 Minor 策略。

LatestMinor——前滾至最新次版本,即使存在所請求的次版本亦不受影響。

LatestMajor ——前滾至最新主版本,即使存在所請求的主版本亦不受影響。

Disable ——不進(jìn)行前滾。僅綁定至指定版本。我們不建議大家在常規用途中使用這(zhè)一選項,因爲其會禁用前滾至最新補丁後(hòu)版本的功能(néng)。僅建議您在測試環境中使用。

Docker 與 cgroup 限制

很多開(kāi)發(fā)人員都(dōu)在利用容器技術打包并運行自己的應用程序。其中的一大重要問題,在于容器的 CPU 或者内存等資源可能(néng)受到限制。我們早在 2017 年就實現了對(duì)内存限制功能(néng)的支持,遺憾的是,我們發(fā)現該實現的主動性不足以將(jiāng)容器環境以可靠方式保持在配置限制之下,意味着即使設置了内存限制(特别是小于 500 MB 的情況),應用程序仍然有可能(néng)出現 OOM 問題。我們已經(jīng)在 .NET Core 3.0 當中修複了這(zhè)一問題。這(zhè)一改進(jìn)意義重大,我們強烈建議使用 .NET Core Docker 的用戶升級至 .NET Core 3.0。

Docker 資源限制功能(néng)構建在 cgroup 基礎之上,而 cgroup 又是一項 Linux 内核功能(néng)。從運行時的角度來看,我們需要以 cgroup 基元爲目标。

大家可以利用 docker run -m 參數來限制容器的可用内存,如下所示,此示例用于創建一個基于 Alpine 且内存容量爲 4 MB 的容(而後(hòu)輸出内存限制):

我們還(hái)添加了新的變更,以更好(hǎo)地支持 CPU 限制(–cpus)。其中包括更新運行時對(duì)十進(jìn)制 CPU 值進(jìn)行四舍五入的方式。如果將(jiāng)—cpus 設置爲(足夠)接近某個較小的整數(例如 1.499999999)的值,則運行時會對(duì)該值進(jìn)行四舍五入(這(zhè)種(zhǒng)情況下將(jiāng)四舍五入爲 1)。結果就是,運行時所使用的 CPU 數量低于需求,從而導緻 CPU 資源不足。通過(guò)對(duì)該值進(jìn)行直接進(jìn)位,運行時在理論上會增加 OS 線程調度程序的壓力,但即使是在最極端的情況下(–cpus=1.000000001,以往 其會被四舍五入爲 1,但現在會直接進(jìn)位爲 2),我們也沒(méi)有發(fā)現 CPU 出現任何性能(néng)下降。

下一步是确保線程池遵循 CPU 限制。線程池算法中有一部分負責計算 CPU 的繁忙時間,也就是計算可用 CPU 容量。通過(guò)在計算 CPU 繁忙時間當中考慮 CPU 限制,我們得以避免線程池在争用中執行的各種(zhǒng)試探操作:一種(zhǒng)方法可能(néng)嘗試分配更多線程以增加 CPU 繁忙時間;但另一種(zhǒng)方法則可能(néng)嘗試分配更少線程,以避免不必要的線程浪費。

默認情況下降低 GC 堆大小

在緻力于改善對(duì) docker 内存限制支持能(néng)力的同時,我們也受到了啓發(fā),并着手對(duì)通用 GC 策略加以更新,旨在爲更爲廣泛的應用程序的内存使用率帶來改善(即使未運行在容器之内)。這(zhè)些變更使得第 0 代預算分配能(néng)夠更好(hǎo)地與現代處理器的緩存大小及緩存層級保持一緻。

我們的團隊成(chéng)員 Damian Edwards 注意到,ASP.NET 基準測試的内存使用量減少了一半,但其它性能(néng)指标并未出現任何負面(miàn)影響。這(zhè)是一項驚人的進(jìn)步!如他所言,這(zhè)些將(jiāng)成(chéng)爲新的默認設置,且不需要對(duì)您的代碼做出任何修改(隻需采用 .NET Core 3.0 即可)。

當然,我們在 ASP.NET 基準測試中觀察到的内存節約效果,可能(néng)代表 / 不代表您的實際體驗。我們希望聽到更多朋友在實際應用程序内存使用量方面(miàn)觀察到的結果。

改善對(duì)多處理器設備的支持能(néng)力

基于 .NET 的 Windows 傳統,GC 需要配合 Windows 處理器組概念才能(néng)支持包含 64 塊以上處理器的計算機。這(zhè)一實現早在 5 到 10 年前的 .NET Framework 當中即已完成(chéng)。但利用 .NET Core,我們最初選擇了 Linux PAL 以實現類似的概念——雖然 Linux 當中不存在這(zhè)一原生概念。此後(hòu),我們在 GC 當中放棄了這(zhè)一概念,并將(jiāng)其轉化爲 Windows APL。

GC 現在公開(kāi)了一個配置開(kāi)關,即 GCHeapAffinitizeRanges,用于在包含 64 個以上處理器的計算機上指定相似的掩碼。

GCLarge Page 支持

Large Pages 或者叫(jiào) Huge Pages 是一項功能(néng),操作系統可利用其構建起(qǐ)大于原生頁面(miàn)大小(通常爲 4K)的内存區域,從而提高調用這(zhè)些大頁面(miàn)的應用程序的性能(néng)表現。

當發(fā)生虛拟到物理地址的轉換時,系統會首先查詢(通常爲并行)被稱爲轉換後(hòu)備緩沖區(TLB)的高速緩存,以檢查是否存在可用于所訪問虛拟地址的可用物理翻譯,以避免進(jìn)行可能(néng)占用大量資源的頁面(miàn)移動操作。每個大頁面(miàn)翻譯都(dōu)需要使用 CPU 内部的一個翻譯緩沖區。該緩沖區的大小通常要比本地頁面(miàn)大三個數量級;這(zhè)能(néng)夠極大提高轉換緩沖區的效率,從而改善内存在頻繁訪問下的性能(néng)。在具有雙層 TLB 的虛拟機當中,這(zhè)一改進(jìn)顯得尤爲重要。

GC 現在能(néng)夠利用 GCLargePages 選項功能(néng)進(jìn)行配置,從而選擇在 Windows 上分配大頁面(miàn)。利用大頁面(miàn)能(néng)夠減少 TLB 遺漏,進(jìn)而在總體上提高應用程序的性能(néng);但是,這(zhè)項功能(néng)也有着自己的局限,應當認真考量。Bing.com 就采用了這(zhè)項功能(néng),并切實獲得了性能(néng)提升。

.NET Core 版本 API

我們在.NET Core 3.0 當中對(duì).NET Core 版本 API 做出改進(jìn),現在它們能(néng)夠返回您所需要的版本信息。這(zhè)些變更雖然在客觀上帶來了便利,但卻存在技術破壞性,而且有可能(néng)影響到依賴現有版本 API 獲取各類信息的應用程序。

現在,大家可以訪問以下版本信息:

Event Pipe 改進(jìn) Event Pipe 現在支持多個會話。這(zhè)意味着大家可以使用 EventListener 在進(jìn)程内使用事(shì)件,同時獲得進(jìn)程外 event pipe 客戶端。

添加了新的 Perf Counters:

GC 中的時間百分比

Gen 0 堆大小

Gen 1 堆大小

Gen 2 堆大小

LOH 堆大小

分配率

加載組件數量

ThreadPool 線程數量

鎖定争用率

ThreadPool 工作條目隊列

ThreadPool 已完成(chéng)工作項比例

現在,大家可以使用同樣的 Event Pipe 基礎設施實現 Profiler 險别。

HTTP/2 支持

現在,我們在 HttpClinet 當中支持 HTTP/2。采用新協議是爲了滿足某些 API 的要求,例如 gRPC 與 Apple Push Notification Service。我們希望未來會有更多服務使用 HTTP/2 協議。此外,ASP.NET 也同樣支持 HTTP/2。

備注:首選 HTTP 協議版本將(jiāng)通過(guò) TLS/ALPN 協商,并僅在服務器選擇使用 HTTP/2 時才加以使用。

分層編譯

分層編譯是 .NET Core 2.1 中的一項可選功能(néng),該功能(néng)使得運行時能(néng)夠更靈活地使用即時(JIT)編譯器,從而在啓動時獲得更佳性能(néng)并最大程度提升吞吐量。.NET Core 3.0 在默認情況下即啓用這(zhè)一功能(néng)。去年,我們對(duì)該功能(néng)做出了一系列改進(jìn),包括針對(duì)各類工作負載(例如網站、PowerShell 以及 Windows 桌面(miàn)應用程序)進(jìn)行測試。性能(néng)确實迎來顯著提升,因此我們決定將(jiāng)其作爲默認選項。

IEEE 浮點改進(jìn)

我們對(duì)浮點 API 進(jìn)行了更新,以符合 IEEE 754-2008 修訂版的要求。.NET Core 浮點項目的目标,在于公開(kāi)所有“必要”運算,以确保其在行爲層面(miàn)符合 IEEE 提出的規範。

解析與格式化修複:

正确解析并舍入任何長(cháng)度的輸入。

正确解析并格式化負零。

通過(guò)進(jìn)行不區分大小寫的檢查,并在适用時允許使用可選前置 + 以正确解析無限與 NaN。

新的 Math API:

BitIncrement/BitDecrement ——對(duì)應于 nextUp 與 nextDown IEEE 運算。二者分别返回大于或者小于輸入内容的最小浮點數。例如,Math.BitIncrement(0.0)將(jiāng)返回 double.Epsilon。

MaxMagnitude/MinMagnitude——對(duì)應于 maxNumMag 與 minNumMag IEEE 運算,二者分别返回大于或者小于輸入内容的值。例如,Math.MaxMagnitude(2.0 -3.0) 將(jiāng)返回 -3.0。

ILogB ——對(duì)應于 logB IEEE 運算,該運算將(jiāng)返回一個整數值,且該值爲輸入參數的以 2 爲底的整數對(duì)數。實際上與 floor(log2(x)) 相同,但舍入誤差最小。

ScaleB——對(duì)應于采用整數值的 scaleB IEEE 運算,其相當于返回 x * pow(2,n) 的值,但舍入誤差最小。

Log2——對(duì)應于 log2 IEEE 運算,返回以 2 爲底的對(duì)數,且舍入誤差最小。

FusedMultiplyAdd ——對(duì)應于 fma IEEE 運算,負責執行積和熔加運算。具體而言,其通過(guò)一次運算完成(chéng)(xy)+ z 運算,同時使舍入誤差最小。以 FusedMultiplyAdd (1e308, 2.0, -1e308) 爲例,其返回值爲 1e308。常規(1e308

2.0)-1e308 將(jiāng)返回 double.PositiveInfinity。

CopySign ——對(duì)應于 copySign IEEE 運算,其返回 x 的值,但同時帶有 y 符号。

.NET 平台相關改進(jìn)

我們添加了一些新的 API,用以訪問某些面(miàn)向(xiàng)性能(néng)的 CPU 指令,包括 SIMD 或 Bit Manipulation 指令集。這(zhè)些指令能(néng)夠在某些場景下實現巨大的性能(néng)提升,例如更高效地并行處理數據。除了公開(kāi)這(zhè)些可供應用程序使用的 API 之外,我們還(hái)開(kāi)始利用相關指令對(duì).NET 庫進(jìn)行提速。

以下 CoreCLR PRs 通過(guò)實現或者使用的方式展示了一部分内部函數:

實現簡單 SSE2 硬件内部函數

實現 SSE 硬件内部函數

Arm64 Base 硬件内部函數

面(miàn)向(xiàng) LocateFound使用 TZCNT 與 LZCNT

現可在 Linux 上支持 TLS 1.3 與 OpenSSL 1.1.1

.NET Core 現在能(néng)夠利用 OpenSSL 1.1.1 中的 TLS 1.3 支持能(néng)力。TLS 1.3 能(néng)夠爲 OpenSSL 團隊提供多項優勢:

通過(guò)減少客戶端與服務器間的往返次數縮短連接時長(cháng)。

通過(guò)消除各種(zhǒng)過(guò)時及不安全的加密算法、同時加密更多連接握手,以提高安全性。

.NET Core 3. 能(néng)夠利用 OpenSSL 1.1.1、OpenSSL 1.1.0 以及 OpenSSL 1.0.2(以及您能(néng)夠在 Linux 系統上找到任何最佳版本)。如果客戶端與服務器均支持 TLS 1.3,且 OpenSSL 1.1.1 可用,則 SslStream 與 HttpClinet 類型將(jiāng)在使用 SslProtocols.None 時選擇 TLS 1.3(系統默認協議)。

.NET Core 後(hòu)續還(hái)將(jiāng)在 Windows 與 MacOS 上支持 TLS 1.3——預計以自動化方式實現,敬請期待。

加密

我們增加了對(duì) AES-GCM 以及 AES-CCM 加密機制的支持,這(zhè)些加密算法將(jiāng)通過(guò) System.Security.Cryptography.AesGcm 與 System.Security.Cryptography.AesCcm 實現。這(zhè)些算法皆屬于帶關聯數據的加密認證(AEAD)算法,同時也是首批被添加至 .NET Core 當中的驗證加密(AE)算法。

.NET Core 3.0 現在支持通過(guò)标準格式導入及導出非對(duì)稱公鑰與私鑰,且無需使用 X.509 證書。

所有密鑰類型(RSA、DSA、ECDsa、ECDiffieHellman)都(dōu)支持 X.509 SubjectPublicKeyInfo 格式的公鑰,以及 PKCS#8 PrivateKeyInfo 與 PKCS#8 EncryptedPrivateKeyInfo 格式的私鑰。此外,RSA 還(hái)支持 PKCS#1 RSAPublicKey 與 PKCS#1 RSAPrivateKey。所有導出方法皆産生 DER 編碼的二進(jìn)制數據,而導入方法也基本相同;如果某一密鑰以文本友好(hǎo)的 PEM 格式存儲,則調用程序將(jiāng)需要先對(duì)内容進(jìn)行 base64 解碼,而後(hòu)才能(néng)進(jìn)行方法導入。

PKCS#8 文件可通過(guò) System.Security.Cryptography.Pkcs.Pkcs8PrivateKeyInfo 類進(jìn)行檢查。

PFX/PKCS#12 文件可分别通過(guò) System.Security.Cryptography.Pkcs.Pkcs12Info 與 System.Security.Cryptography.Pkcs.Pkcs12Builder 進(jìn)行檢查與修改。

支持新的日本年号(令和)

2019 年 5 月 1 日,日本開(kāi)始使用新的年号——令和。因此,支持日語日曆的軟件(例如 .NET Core)必須進(jìn)行更新以支持這(zhè)一新年号。.NET Core 與 .NET Framework 已經(jīng)更新,現在可以正确處理新年号下的日文日期格式與解析結果。

.NET 依賴于操作系統或其他更新以正确處理令和日期。如果您或者您的客戶使用 Windows 系統,請下載 Windows 版本的最新更新。如果您運行的是 MacOS 或者 Linux,請下載并安裝支持日本新年号的 ICU 64.2 版本。

Assembly Load Context 改進(jìn)

關于 AssemblyLoadContext 的改進(jìn):

實現上下文命名

添加 ALC 枚舉功能(néng)

對(duì) ALC 内程序集進(jìn)行枚舉的功能(néng)

實現類型具體化——旨在簡化實例化(簡單場景不需要自定義類型)

通過(guò)將(jiāng) AssemblyDependencyResolyer 與自定義 AssemblyLoadContext 加以結合,應用程序將(jiāng)能(néng)夠在加載插件的過(guò)程中,從各個正确位置加載該插件所需要的依賴項,且某一插件的依賴項不會與其他插件的依賴項發(fā)生沖突。

Assembly 可卸載性

Assembly 的可制裁性是 AssemblyLoadContext 中提供的一項新功能(néng)。從 API 的角度來看,這(zhè)項新功能(néng)具有極高的透明度,且面(miàn)向(xiàng)部分新 API 公開(kāi)。其允許開(kāi)發(fā)人員對(duì)加載程序的上下文進(jìn)行卸載,從而釋放原本被實例化類型、靜态字段以及程序集本身所占用的内存。應用程序可以通過(guò)這(zhè)種(zhǒng)機制實現程序集的永久加載與卸載,且不會引發(fā)内存洩漏。

我們希望這(zhè)項新功能(néng)被用于以下場景:

需要動态插件加載與卸載的插件使用場景。

對(duì)代碼的動态編譯、運行以及刷新。适用于網站、腳本引擎等。

加載程序集以進(jìn)行自我檢查(例如 ReflectionOnlyLoad),但在大多數情況下 MetadataLoadContext 仍然是更好(hǎo)的選擇。

利用 MetadataLoadContext 讀取 Assembly 元數據

我們添加了 MetadataLoadContext,希望在不影響調用程序域的前提下讀取 assembly 元數據。各 assembly 這(zhè)以數據的形式讀取,其中包括與當前運行時環境不同的各類架構及平台上的 assembly。MetadataLoadContext 與 ReflectionOnlyLoad 存在一定交集,但後(hòu)者僅适用于 .NET Framework。

MetdataLoadContext 目前通過(guò) System.Reflection.MetadataLoadContext 軟件包發(fā)布,其屬于 .NET Standard 2.0 軟件包。

MetadataLoadContext 的适用場景包括設計時功能(néng)、構建時工具與運行時點亮功能(néng)等需要將(jiāng)一組 assembly 作爲數據進(jìn)行檢查,并在執行檢查後(hòu)釋放所有文件鎖與内存的場景。

Native Hosting 示例

.NET Core 團隊還(hái)發(fā)布了一個 Native Hosting 示例,其中展示了在本機應用程序當中托管 .NET Core 的相關最佳實踐。

作爲 .NET Core 3.0 中的組成(chéng)部分,我們現在面(miàn)向(xiàng) .NET Core 本地主機公開(kāi)了這(zhè)一原本隻通過(guò)官方 .NET Core 主機爲 .NET Core 托管應用程序提供的功能(néng)。此項功能(néng)主要與 assembly 加載相關,利用這(zhè)項功能(néng)可幫助大家更輕松地構建能(néng)夠利用 .NET Core 完整功能(néng)集的本地主機。

其他 API 改進(jìn)

我們曾在 .NET Core 2.1 版本當中對(duì) Span、Memory 以及其他相關類型做出優化。現在,span construction、切片、解析以及格式化等常規操作的執行效果將(jiāng)有所提升。此外,String 等類型也得到了明顯改進(jìn),能(néng)夠在與 Dictionary 及其他集合共同充當鍵時擁有更好(hǎo)的執行效率。所有改進(jìn)開(kāi)箱即用,無需對(duì)您的代碼做出任何變更。

下面(miàn)來看其它最新改進(jìn):

Brotli 内置 HttpClient 支持能(néng)力

ThreadPool.UnsafeQueueWorkItem(IThreadPoolWorkItem)

Unsafe.Unbox

CancellationToken.Unregister

複雜算術運算符

Socket APIs for TCP 仍然有效

StringBuilder.GetChunks

IPEndPoint 解析

RandomNumberGenerator.GetInt32

System.Buffers.SequenceReader

默認情況下,應用程序現在具有原生可執行文件

.NET Core 應用程序現在擁有自己的原生可執行文件。對(duì)于依賴框架的應用程序而言,這(zhè)是一項前所未有的新功能(néng)。在此之前,隻有獨立應用程序具有可執行文件。這(zhè)些新的可執行文件,將(jiāng)在效果上與此前的原生可執行文件保持一緻:

您可以雙擊可執行文件以啓動對(duì)應應用程序。

您可以在 Windows 上使用 myapp.exe,或者在 Linux 及 MacOS 上使用./myapp 通過(guò)命令提示符啓動應用程序。

作爲 build 的組成(chéng)部分,新生成(chéng)的可執行文件將(jiāng)與您的操作系統以及 CPU 相匹配。例如,如果您使用的是 Linux x64 計算機,那麼(me)可執行文件將(jiāng)僅可在該類型的計算機上運行——無法在 Windows 以及 Linux ARM 計算機上運行。這(zhè)是因爲可執行文件使用本機代碼(例如 C++)。如果要定位爲其他機器類型,則需要在發(fā)布時使用對(duì)應的運行時參數。如果願意,您也可以繼續使用 dotnet 命令啓動應用程序,而不使用原生可執行文件。

利用 ReadyToRun 鏡像優化 .NET Core 應用

通過(guò)將(jiāng)應用程序 assemblies 編譯爲 ReadyToRun(R2R)格式,可以改進(jìn) .NET Core 應用程序的啓動速度。R2R 是一種(zhǒng)提前(AOT)編譯格式,在 .NET Core 3.0 版本中以可選功能(néng)的形式提供。

R2R 二進(jìn)制文件能(néng)夠減少應用程序加載時 JIT 需要完成(chéng)的工作量,從而提高啓動性能(néng)。二進(jìn)制文件當中包含與 JIT 産生的代碼相似的本機代碼,能(néng)夠通過(guò)分擔 JIT 的負載壓力帶來更理想的啓動性能(néng)。R2R 二進(jìn)制文件體積較大,因爲其中既包含中間語言(IL)代碼(某些情況下仍然需要此代碼),同時包含同一代碼的本機版本,用以改善啓動速度。

要啓用 R2R 編譯:

將(jiāng) PublishReadyToRun 屬性設置爲 true。

使用 RuntimeIdentifie 顯式參數發(fā)布。

備注:在編譯應用程序 assemblies 時,生成(chéng)的本機代碼將(jiāng)特定于當前平台與架構(因此,大家在發(fā)布時必須指定有效的 RuntimeIdentifier)。

以下爲具體示例:

使用以下命令進(jìn)行發(fā)布:

備注:RuntimeIdentifier 可設置爲其他操作系統或者芯片類型,亦可在項目文件内進(jìn)行設置。

Assembly Linking

.NET core 3.0 SDK 附帶一款工具,可通過(guò)分析 IL 與修剪未使用的 assemblies 以降低應用程序的體積。這(zhè)是 .NET Core 3.0 中的另一項發(fā)行時可選功能(néng)。

在 .NET Core 當中,我們可以随時發(fā)布包含代碼運行所需的一切元素的自包含應用程序,而無需在部署目标上安裝 .NET。在某些情況下,該應用僅需要框架中的一小部分即可運行,因此修剪掉不必要的框架部分能(néng)夠有效降低應用程序體積。我們利用 IL linker 對(duì)應用程序的 IL 進(jìn)行掃描,從而檢測出哪些代碼确有必要,而後(hòu)對(duì)未使用的框架庫進(jìn)行修剪。這(zhè)能(néng)夠顯著降低某些應用程序的體積。一般來講,小型工具控制台類應用程序的瘦身效果最爲明顯,因爲其通常使用框架中的較小子集,且調整難度更低。

要使用 linker 工具:

將(jiāng) PublishTrimmed 的屬性設置爲 true。

將(jiāng) RuntimeIdentifier 作爲顯式參數進(jìn)行發(fā)布。

以下爲相關示例:

使用以下命令進(jìn)行發(fā)布:

備注:RuntimeIdentifier 可設置爲其他操作系統或者芯片類型,亦可在項目文件内進(jìn)行設置。

根據應用程序代碼的實際調用情況,所發(fā)布的輸出結果將(jiāng)包含框架庫中的一個子集。對(duì)于最簡單的 helloworld 應用,linker 工具能(néng)夠將(jiāng)應用程序體積縮小 68 MB 到 28 MB。

在修剪之後(hòu),需要使用反射或者相關動态功能(néng)的應用程序或者框架(包括 ASP .NET Core 以及 WPF)通常無法正常執行,這(zhè)是因爲 linker 無法識别這(zhè)種(zhǒng)動态行爲,因此一般不能(néng)确定反射操作在運行時中需要的框架類型。要修剪這(zhè)類應用程序,大家需要告知 linker 相關代碼當中所依賴的各類工具包或框架以及各種(zhǒng)相關信息類型。請确保您在修剪之後(hòu)對(duì)應用程序進(jìn)行全面(miàn)測試,我們也正在 .NET 5 當中對(duì)這(zhè)一體驗做出改進(jìn)。

關于 IL Linker 的更多細節信息,請參閱說明文檔或者訪問 mono/linker 庫。

備注:在 .NET Core 之前的版本當中,ILLink Tasks 以外部 NuGet 軟件包的形式提供,其中包含多種(zhǒng)相同功能(néng)。但相關軟件包現已不再受到支持,請更新至 .NET Core 3.0 SDK 以獲取我們爲您準備的全新體驗.

Linker 與 R2R 編譯器可同時作用于一款應用程序。一般來講,Linker 能(néng)夠使您的應用程序體積更小,而 R2R 則能(néng)夠再次恢複其體積,并在性能(néng)上帶來顯著提升。大家可以在各種(zhǒng)配置當中進(jìn)行測試,以了解各個選項帶來的具體影響。

發(fā)布單文件可執行文件

現在,大家可以利用 dotnet publish 命令發(fā)布單文件可執行文件了。這(zhè)種(zhǒng)形式的單一 EXE 實際上是一個自解壓可執行文件,其中以資源形式包含所有依賴項(包括本地依賴項)。在啓動時,它會將(jiāng)所有依賴項複制到某個臨時目錄,通過(guò)該目錄進(jìn)行加載。依賴項隻需要解壓一次,後(hòu)續啓動將(jiāng)速度極快,不再存在任何性能(néng)損失。

大家可以通過(guò)在項目文件中添加 PublishSingleFile 屬性,或者在命令行中添加新開(kāi)關的方式啓用這(zhè)一發(fā)布選項。

要生成(chéng)獨立的單 EXE 應用程序,以下示例爲 64 位 Windows 系統下的命令:

備注:RuntimeIdentifier 可設置爲其他操作系統或者芯片類型,亦可在項目文件内進(jìn)行設置。

若需了解更多細節信息,請參閱單文件捆綁器說明文檔。

Assembly 修剪器、提前編譯(通過(guò) crossgen)以及單文件捆綁功能(néng)皆爲 .NET Core 3.0 中提供的全新選項,大家可以根據需求獨立使用或者以組合方式使用。相信一部分用戶可能(néng)喜愛通過(guò)提前編譯器提供的單 exe 發(fā)布選項,而非我們在.NET Core 3.0 當中提供的自解壓可執行文件方法。.NET 5 發(fā)行版當中將(jiāng)正式提供提前編譯器方法。

dotnet build 現在可複制依賴項

dotnet build 現在能(néng)夠在 build 操作過(guò)程當中,將(jiāng)應用程序中的 NuGet 依賴項從 NuGet 緩存複制到 build 輸出文件夾内。在此版本之前,各依賴項僅能(néng)作爲 dotnet publish 中的一部分進(jìn)行複制。此次變更使您能(néng)夠利用 xcopy 將(jiāng) build 輸出至不同計算機當中。

除此之外,您還(hái)需要單獨發(fā)布 linking 以及 razor page publishing 等操作。

2

.NET Core 工具:本地安裝

.NET Core 工具也經(jīng)過(guò)更新以支持本地安裝。這(zhè)些工具比 .NET Core 2.1 版本中的原有全局工具更強大。

本地安裝具有以下特性:

限制工具的使用範圍。

始終使用該工具的某一特定版本,該版本可能(néng)不同于全局安裝工具或者其它本地安裝工具。具體基于本地工具 manifest 文件中定義的版本。

可使用 dotnet 命令啓動,例如 dotnet mytool。

備注:請參閱本地工具早期預覽版說明文檔以了解更多細節信息。

.NET Core SDK 安裝程序現在將(jiāng)就地升級

Windows 版本的 .NET Core SDK MSI 安裝程序將(jiāng)迎來就地升級。這(zhè)將(jiāng)減少開(kāi)發(fā)者計算機及生産計算機上所需安裝的 SDK 數量。

此項升級策略將(jiāng)專門針對(duì) .NET Core SDK 功能(néng)範圍。各功能(néng)範圍在版本号中以最後(hòu)三位數字中的百位體現,例如 3.0.101 與 3.0.201 代表兩(liǎng)個不同的版本功能(néng)範圍,而 3.0.101 與 3.0.199 則處于同一版本功能(néng)範圍。

這(zhè)意味着當 .NET Core SDK 3.0.101 正式發(fā)布并安裝完畢後(hòu),.NET Core SDK 3.0.100 將(jiāng)被從計算機中删除(如果存在)。當 .NET Core SDK 3.0.200 可用并安裝在同一台計算機上時,.NET Core SDK 3.0.101 則不會被删除。在這(zhè)種(zhǒng)情況下,系統仍將(jiāng)默認使用 .NET Core SDK 3.0.200,但如果將(jiāng)其配置爲通過(guò) global.json 起(qǐ)效,則系統仍然使用 .NET Core SDK 3.0.101(或者更高版本的.1xx 版本)。

這(zhè)種(zhǒng)方法與 global.json 的行爲保持一緻,允許在各補丁版本之間進(jìn)行前滾 ,但無法跨越 SDK 功能(néng)範圍。因此,通過(guò) SDK 安裝程序并進(jìn)行升級,可确保應用程序不會因缺少 SDK 而發(fā)生錯誤。對(duì)于已經(jīng)安裝了 Visual Studio 必要 SDK 的用戶,其功能(néng)範圍也將(jiāng)與 Visual Studio 安裝情況保持一緻。

若需了解更多細節信息,請參閱:

.NET Core 版本控制

删除.NET Core SDK 版本

.NET Core SDK 體積改進(jìn)

在 .NET Core 3.0 當中,.NET Core SDK 的體積明顯更小。主要原因在于,我們轉而采用出于各種(zhǒng)目的(引用 assembiles、框架、模闆等)的專用“内置包”,從而改變了我們構建 SDK 的方式。在以往的版本(包括 .NET Core 2.2)當中,我們一直利用 NuGet 軟件包構建 SDK,但其中包含大量并不需要的構件,且對(duì)存儲空間造成(chéng)嚴重浪費。

.NET Core 3.0 SDK 體積(括号中爲體積變量)

Linux 與 MacOS 版本的體積變化最爲顯著,相比之下 Windows 版本的改進(jìn)較小,這(zhè)是因爲我們在 .NET Core 3.0 當中添加了 WPF 與 Windows Forms。令人驚訝的是,盡管新增了 WPF 與 Windows Forms,安裝程序的體積仍然比原先小了一點。

大家也可以在 .NET Core SDK Docker 鏡像當中感受到這(zhè)一瘦身效果(僅限于 x64 Debian 與 Alpine)。

大家可以在 .NET Core 3.0 SDK 體積改進(jìn)文檔中了解我們如何計算這(zhè)些文件的大小。這(zhè)裡(lǐ)提供詳細的說明,您可以遵循同樣的方法在自己的環境中運行測試。

Docker 發(fā)布更新

微軟各團隊目前都(dōu)在面(miàn)向(xiàng)微軟容器注冊表(MCR)發(fā)布新的容器鏡像。這(zhè)一變化主要有兩(liǎng)大原因:

將(jiāng)微軟提供的容器鏡像協同至多個注冊表,包括 Docker Hub 與 Red Hat。

利用微軟 Azure 作爲全球 CDN 以交付微軟提供的容器鏡像。

在.NET 團隊,我們目前將(jiāng)所有 .NET Core 鏡像發(fā)布至 MCR。我們在 Docker Hub 上維護有自己的主頁,并打算長(cháng)期保持運營。在另一方面(miàn),MCR 并不提供類似的頁面(miàn),但可以通過(guò) Docker Hub 等公共注冊表爲用戶提供與鏡像有關的信息。Microsoft.dotnet 以及 microsoft.dotnet-nightly 等舊有代碼庫鏈接現在都(dōu)已經(jīng)指向(xiàng)新的地址。不過(guò)舊有位置中的各鏡像仍將(jiāng)存在,不會被删除。

在支持生命周期之内,我們將(jiāng)繼續爲 .NET Core 各個版本的代碼庫提供浮動标記服務。例如,2.1-sdk、2.2-runtime 以及 lastest 就屬于此類浮動标記。像 2.1.2-sdk 這(zhè)類包含三個數字的标簽將(jiāng)不再提供,我們已經(jīng)在版本号内加以體現。接下來,我們將(jiāng)僅通過(guò) MCR 支持 .NET Core 3.0 鏡像。

例如,現在用于提取 3.0 SDK 鏡像的正确标簽字符串應該爲:

新的 MCR 字符串將(jiāng)由 docker pull 以及 Dockerfile FROM 語句共同使用。

感興趣的朋友可以參閱微軟容器注冊表中的現有 .NET Core 鏡像以了解更多細節信息。

SDK Docker 鏡像中包含 PowerShell Core

應社區的要求,PowerShell Core 已經(jīng)被添加至 .NET Core SDK Docker 容器鏡像當中。PowerShell Core 是一套跨平台(Windows、Linux 以及 MacOS)自動化與配置工具 / 框架,能(néng)夠與大家的現有工具良好(hǎo)協作,并針對(duì)結構化數據(例如 JSON)CSV、XML 等)、REST API 以及對(duì)象模型進(jìn)行了優化。其中包含一個命令行 shell、一種(zhǒng)相關腳本語言以及一套用于處理 cmdlets 的框架。

現在,大家可以通過(guò)以下 Docker 命令將(jiāng) PowerShell Core 視爲 .NET Core SDK 容器鏡像中的一部分:

目前隻有兩(liǎng)種(zhǒng)將(jiāng) PowerShell 引入 .NET Core SDK 容器鏡像的方法,具體如下:

面(miàn)向(xiàng)任意操作系統利用 PowerShell 語法編寫 .NET Core 應用程序 Dockerfiles。

編寫能(néng)夠輕松實現容器化的 .NET Core 應用程序 / 庫構建邏輯。

以下爲容器化 build(存儲卷挂載)的 PowerShell 啓動語法示例:

爲了讓第二條示例命令正常起(qǐ)效,我們需要在 Linux 上确保.ps1 文件具有以下格式,并需要利用 Unix(LF)而非 Windows(CRLF)作爲行尾以執行格式化:

備注:PowerShell Core 目前已經(jīng)作爲.NET Core 3.0 SDK 容器鏡像的一部分進(jìn)行發(fā)布,而不再歸屬于 .NET Core 3.0 SDK。

紅帽軟件支持

2015 年 4 月,我們宣布 .NET Core 將(jiāng)全面(miàn)登陸 Red Hat Enterprise Linux。通過(guò)與紅帽方面(miàn)的出色工程合作,.NET Core 1.0 于 2016 年 6 月以組件的形式出現在紅帽系列軟件當中。另外,在與紅帽工程師們的持續交流當中,我們也了解到 Linux 社區在軟件發(fā)布方面(miàn)的反饋與意見。

過(guò)去四年以來,紅帽公司先後(hòu)發(fā)布了多次面(miàn)向(xiàng) .NET Core 的更新與大版本升級,包括 2.1 與 2.2 版本。在 .NET Core 2.2 版本當中,紅帽公司將(jiāng)其 .NET Core 産品擴展至包括 OpenShift 在内的多個平台。而随着 RHEL 8 的發(fā)布,我們也高興地看到微軟 .NET Core 2.1 以及即將(jiāng)推出的 3.0 版本都(dōu)被納入紅帽 Application Streams 當中。

3

總結

.NET Core 3.0 是 .NET Core 發(fā)展曆程中的又一重要新版本,其中帶來了大量改進(jìn)。我們建議大家盡快着手采用新的 .NET Core 3.0。新版本通過(guò)多種(zhǒng)方式對(duì) .NET Core 做出巨大改進(jìn),例如顯著降低了 SDK 的體積、極大提升對(duì)于關鍵場景(例如容器以及 Windows 桌面(miàn)應用程序)的支持效果。受到篇幅所限,這(zhè)裡(lǐ)無法一一列出其它小的改進(jìn),但相信随着時間的推移,大家一定能(néng)夠從這(zhè)些細節增強中受益。

最後(hòu),希望大家能(néng)夠在接下來的使用當中與我們分享體驗與感受。希望開(kāi)發(fā)者喜歡 .NET Core 3.0,我們也熱切希望根據大家的喜好(hǎo)對(duì)産品進(jìn)行打磨。

https://devblogs.microsoft.com/dotnet/announcing-net-core-3-0/

責任編輯:中山網站建設
 【網訊網絡】國(guó)家高新技術企業》十年專注軟件開(kāi)發(fā),網站建設,網頁設計,APP開(kāi)發(fā),小程序,微信公衆号開(kāi)發(fā),定制各類企業管理軟件(OA、CRM、ERP、訂單管理系統、進(jìn)銷存管理軟件等)!服務熱線:0760-88610046、13924923903,http://www.wansion.net

您的項目需求咨詢熱線:0760-88610046(國(guó)家高新技術企業)

*請認真填寫需求,我們會在24小時内與您取得聯系。