2019-09-30
作者丨Richard Lander 譯者丨核子可樂(lè) 策劃丨趙鈺瑩
近日,.NET Core 3.0 正式發(fā)布。此次新版本包含一系列重要改進(jìn),添加了 Windows Forms 與 WPF、添加新的 JSON API、對(duì) ARM64 的支持能力以及全面提高的性能水平等。此外,C# 8 也是此次新版本的重要組成部分,其中包含可空、異步流以及更多模式。F# 4.7 則專注于放寬語(yǔ)法限制,并專門匹配 .NET Standard 2.0。開(kāi)發(fā)者現(xiàn)在可以立即將原有項(xiàng)目更新為 .NET Core 3.0,此次新版本與原有版本兼容,大家可以放心體驗(yàn)。
根據(jù)微軟博客的介紹,開(kāi)發(fā)者可以面向 Windows、MacOS 以及 Linux 等系統(tǒng)平臺(tái)下載 .NET Core 3.0 :
.NET Core 3.0 SDK 與運(yùn)行時(shí)
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 亦同時(shí)發(fā)布,且需要更新才能確保 .NET Core 3.0 與 Visual Studio 的協(xié)同使用。.NET Core 3.0 為 Visual Studio 2019 16.3 中的組成部分,開(kāi)發(fā)者可以選擇直接升級(jí)至 Visual Studio 2019 16.3,從而立刻獲取 .NET Core。
感謝所有為 .NET Core 3.0 做出貢獻(xiàn)的朋友們!此次最新版本的發(fā)布源自數(shù)百位團(tuán)隊(duì)成員的努力,也包括技術(shù)社區(qū)的重大貢獻(xiàn)。
發(fā)行說(shuō)明:
.NET Core 3.0 發(fā)行說(shuō)明
.NET Core 2.2 -> 3.0 API 的區(qū)別
.NET Core 3.0 貢獻(xiàn)者名單
GitHub 發(fā)行版
關(guān)于 .NET Core 3.0 的 GitHub 問(wèn)題解答
1
3.0 版本,開(kāi)發(fā)者需要了解什么?
在深入探究 .NET Core 3.0 中的全部新功能之前,我們首先需要強(qiáng)調(diào)幾項(xiàng)關(guān)鍵性的改進(jìn)與指導(dǎo)內(nèi)容。以下是整理出的要點(diǎn)清單:
.NET Core 3.0 已經(jīng)在 dot.net 以及 Bing.com 上托管了幾個(gè)月,通過(guò)了一系列嚴(yán)苛的測(cè)試。眾多其他微軟團(tuán)隊(duì)也將很快在生產(chǎn)流程當(dāng)中通過(guò) .NET Core 3.0 部署一系列大型工作負(fù)載。
多種組件的性能得到顯著提升,感興趣的朋友可以點(diǎn)擊此處參閱 .NET Core 3.0 的性能改進(jìn)說(shuō)明。
C# 8 加入了異步流、范圍 / 索引、更多模式以及可為空的引用類型。可為空意味著可以直接發(fā)現(xiàn)那些導(dǎo)致 NullReferenceException 問(wèn)題的代碼缺陷。框架庫(kù)的最底層注釋也已添加完成,以幫助了解何時(shí)為 Null。
F# 4.7 致力于通過(guò)隱式 yield 表達(dá)式及相關(guān)語(yǔ)法降低某些操作的實(shí)現(xiàn)難度。其中還包含對(duì) LangVersion 的支持,提供 nameof 并可以預(yù)覽形式打開(kāi)靜態(tài)類。F# Core 核心庫(kù)現(xiàn)在還與 .NET Standard 2.0 相匹配。您可以點(diǎn)擊此處參閱 F# 4.7 發(fā)布公告中的細(xì)節(jié)信息。
.NET Standard 2.1 增加了可與 .NET Core 以及 Xamarin 共同使用的代碼類型集。.NET Standar 2.1 當(dāng)中包含 .NET Core 2.1 以及之后版本中的所有類型。
Windows 桌面應(yīng)用現(xiàn)已面向 Windows Forms 與 WPF(開(kāi)源)得到 .NET Core 支持。其中,WPF 設(shè)計(jì)器為 Visual Studio 2019 16.3 版本中的組成部分。Windows Forms 設(shè)計(jì)器仍處于預(yù)覽狀態(tài),并可通過(guò) VSIX 下載的形式獲取。
.NET Core 應(yīng)用現(xiàn)在默認(rèn)具備可執(zhí)行文件。在以往的發(fā)行版中,應(yīng)用需要通過(guò) dotnet 命令方啟動(dòng),例如 dotnet myapp.dll。現(xiàn)在,可以通過(guò)應(yīng)用特定可執(zhí)行文件實(shí)現(xiàn)應(yīng)用啟動(dòng),例如 myapp 或者./myapp,具體視使用的操作系統(tǒng)而定。
高性能 JSON API 加入新版本,適用于 reader/writer、對(duì)象模型以及序列化場(chǎng)景等。這些 API 在 Span 基礎(chǔ)之上重新構(gòu)建而成,且在底層使用 UTF8(而非 string 等 UTF16)。這些 API 能夠?qū)⒎峙湫枨罂刂圃谧畹统潭龋瑥亩岣咝阅堋p少垃圾收集器的工作量。具體請(qǐng)參閱.NET Core 3.0 中的 JSON 未來(lái)發(fā)展說(shuō)明。
默認(rèn)情況下,垃圾收集器的內(nèi)存占用量得到了顯著削減。對(duì)于將眾多應(yīng)用程序托管在同一服務(wù)器之上的使用場(chǎng)景,這項(xiàng)改進(jìn)可謂意義重大。垃圾收集器本身也得到了更新,能夠利用 64 核及以上設(shè)備的大量計(jì)算核心。
.NET Core 已針對(duì) Docker 進(jìn)行了增強(qiáng),以使 .NET 應(yīng)用程序能夠在容器中以可預(yù)測(cè)的方式高效運(yùn)作。在容器配置中的內(nèi)存或 CPU 資源有限時(shí),目前的垃圾收集器與線程池更新結(jié)果也能帶來(lái)更好的運(yùn)作效果。.NET Core docker 鏡像也變得更小,其中 SDK 鏡像的瘦身效果尤其明顯。
Raspberry Pi 與 ARM 芯片現(xiàn)已得到支持,可配合遠(yuǎn)程 Visual Studio 調(diào)試程序等工具實(shí)現(xiàn)物聯(lián)網(wǎng)開(kāi)發(fā)。開(kāi)發(fā)者可部署應(yīng)用以監(jiān)聽(tīng)各傳感器,同時(shí)將消息或者圖像輸出至顯示器上,整個(gè)過(guò)程皆可通過(guò)新的 GPIO API 實(shí)現(xiàn)。ASP.NET 則可用于將數(shù)據(jù)公布于 API 或者以站點(diǎn)的形式對(duì)物網(wǎng)設(shè)備進(jìn)行配置。
.NET Core 3.0 即為“當(dāng)前”版本,我們計(jì)劃在 2019 年 11 月推出下一代 .NET Core 3.1 版本。.NET Core 3.1 將為長(zhǎng)期支持(LTS)版本(周期至少為 3 年)。我們建議您首先采用 .NET Core 3.0,而后更新至 3.1 版,升級(jí)過(guò)程將非常輕松。
.NET Core 2.2 將于今年 12 月 23 日停止服務(wù),具體情況請(qǐng)參閱 .NET Core 支持策略。
.NET Core 3.0 將通過(guò) RHEL 8 的紅帽 Applicaltion Streams 交付,這也是我們與紅帽公司多年合作的最新成果。
對(duì)于希望在 Windows 上使用 .NET Core 3.0 的用戶,將必須升級(jí)至 Visual Studio 2019 16.3。
對(duì)于希望在 Mac 上使用 .NET Core 3.0 的用戶,將必須升級(jí)至 Visual Studio for Mac 8.3。
Visual Studio Code 用戶應(yīng)始終使用最新版本的 C# 擴(kuò)展,以確保能夠正常支持最新方案,包括與 .NET Core 3.0 的匹配。
.NET Core 3.0 的 Azure App Serivce 部署目前正在進(jìn)行當(dāng)中。
.NET Core 3.0 的 Azure Dev Ops 部署即將推出。我們將在準(zhǔn)備就緒之后發(fā)布更新。
平臺(tái)支持
.NET Core 3.0 將在以下操作系統(tǒng)平臺(tái)上得到支持:
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 應(yīng)用只適用于 Windows 操作系統(tǒng)。
芯片支持情況:
x64,Windows、macOS 以及 Linux
x86,Windows
ARM32,Windows 與 Linux
ARM64,Linux (kernel 4.14+)
備注:請(qǐng)確保 .NET Core 3.0 ARM64 部署方案采用 Linux 內(nèi)核 4.14 或者更新版本。例如,Ubuntu 18.04 能夠滿足這一條件,但 16.04 版本無(wú)法支持。
WPF 與 Windows Forms
開(kāi)發(fā)者可以在 Windows 系統(tǒng)上利用 .NET Core 3 構(gòu)建 WPF 與 Windows Forms 應(yīng)用從項(xiàng)目起步之初,我們就制定了強(qiáng)大的兼容性目標(biāo),旨在保證桌面應(yīng)用程序能夠從 .NET Framework 輕松遷移至 .NET Core 當(dāng)中。我們已經(jīng)收到眾多開(kāi)發(fā)人員的反饋,了解到他們已經(jīng)成功將自己的應(yīng)用遷移至 .NET Core 3.0,且整個(gè)流程非常輕松便捷。從了盡可能降低對(duì)開(kāi)發(fā)人員的影響,WPF 以及 Windows Forms 沒(méi)有受到任何影響,其仍可在 .NET Core 上正常運(yùn)行。事實(shí)上,項(xiàng)目本身進(jìn)行了重大調(diào)整,但我們認(rèn)為不對(duì)用戶造成影響才是最好的調(diào)整方式。
下圖所示為一款 .NET Core Windows Forms 應(yīng)用:
Visual Studio 2019 16.3 已經(jīng)支持創(chuàng)建能夠匹配 .NET Core 的 WPF 應(yīng)用。其中包括新的模板、經(jīng)過(guò)更新的 XAML 設(shè)計(jì)器以及 XMAL Hot Reload。該設(shè)計(jì)器類似于現(xiàn)有 XAML 設(shè)計(jì)器(能夠匹配.NET Framework),但二者在體驗(yàn)上仍然略有不同。
從技術(shù)層面來(lái)看,最大的區(qū)別在于面向 .NET Core 的設(shè)計(jì)器采用新的接口進(jìn)程(wpfsurface.exe)以僅運(yùn)行針對(duì) .NET Core 版本的運(yùn)行時(shí)代碼。以往,.NET Framework WPF 設(shè)計(jì)器進(jìn)程(xdesproc.exe)本身即為承載設(shè)計(jì)器的 WPF .NET Framework 進(jìn)程;由于運(yùn)行時(shí)不兼容,我們無(wú)法使用 WPF .NET Framework 進(jìn)程(在本示例為中 Visual Studio)將兩個(gè)版本的 .NET(即 .NET Framework 與 .NET Core)加載至同一進(jìn)程當(dāng)中。這意味著設(shè)計(jì)器在一定程度上(例如設(shè)計(jì)器擴(kuò)展)無(wú)法以同樣的方式運(yùn)作。如果正在編寫設(shè)計(jì)器擴(kuò)展,我們建議認(rèn)真閱讀 XAML 設(shè)計(jì)器擴(kuò)展遷移文檔。
下圖所示為顯示在新設(shè)計(jì)器當(dāng)中的 WPF 應(yīng)用:
Windows Forms 設(shè)計(jì)器目前仍處于預(yù)覽狀態(tài),可以單獨(dú)進(jìn)行下載。其將在后續(xù)更高版本內(nèi)被添加至 Visual Studio 當(dāng)中。該設(shè)計(jì)器的當(dāng)前預(yù)算版包含對(duì)最常用控件以及底層功能的支持。我們將通過(guò)每月更新不斷對(duì)該設(shè)計(jì)器做出更新。我們目前不建議大家將自己的 Windows Forms 應(yīng)用程序移植至 .NET Core,特別是在高度依賴設(shè)計(jì)器的情況下。希望開(kāi)發(fā)者體驗(yàn)?zāi)壳暗脑O(shè)計(jì)器預(yù)覽版,并積極向我們反饋問(wèn)題。
另外,大家也可以利用 .NET CLI 通過(guò)命令行進(jìn)行桌面應(yīng)用程序的創(chuàng)建與構(gòu)建。例如,您可以通過(guò)以下命令快速創(chuàng)建一個(gè)新的 Windows Forms 應(yīng)用:
您也可以利用同樣的流程創(chuàng)建 WPF 應(yīng)用:
早在 2018 年 12 月,我們就將 Windows Forms 與 WPF 轉(zhuǎn)化為開(kāi)源項(xiàng)目。很高興看到,目前技術(shù)社區(qū)以及 Windows Forms 及 WPF 團(tuán)隊(duì)正共同努力以改進(jìn)這兩套 UI 框架。在 WPF 方面,我們最初在 GitHub 庫(kù)中只擁有少量代碼,但目前幾乎全部 WPF 代碼都已經(jīng)發(fā)布至 GitHub。隨著時(shí)間的推移,未來(lái)還將有更多組件出現(xiàn)。與其他 .NET Core 項(xiàng)目一樣,這些新的庫(kù)將成為 .NET Foundation 的一部分,并遵循 MIT 開(kāi)源許可。
System.Windows.Forms.DataVisualization 軟件包(包含圖表控件)目前也適用于新的 .NET Core 版本。大家現(xiàn)在可以將這些控制添加到您的 .NET Core WinForms 應(yīng)用程序當(dāng)中。該圖表控件的源代碼可從 Github 上的 dotnet/winforms-datavisualization 處獲取。控件本身已經(jīng)進(jìn)行了調(diào)整,以簡(jiǎn)化面向 .NET Core 3 的移植過(guò)程,但我們并不打算對(duì)其做出大規(guī)模更新。
Windows 原生互操作
Windows 以常規(guī) API、COM 以及 WinRT 的形式提供豐富的原生 API。我們也從 .NET Core 1.0 時(shí)代起即提供對(duì) P/Invoke 的支持;在此次 .NET Core 3.0 當(dāng)中,我們進(jìn)一步添加了 CoCreate COM API、主動(dòng) WinRT API,以及將托管代碼以 COM 組件形式處理等功能。很多開(kāi)發(fā)人員都就這些功能向我們提出申請(qǐng),我們相信其正式推出也將給大家的日常工作帶來(lái)巨大便利。
去年下半年,我們宣布已經(jīng)設(shè)法通過(guò) .NET Core 實(shí)現(xiàn)了 Excel 自動(dòng)化。那絕對(duì)是個(gè)有趣的時(shí)刻。在底層,我們的展示利用到 COM 互操作機(jī)制,例如 NOPIA、對(duì)象等效性以及自定義編組器等等。現(xiàn)在,您可以在擴(kuò)展示例當(dāng)中親自體驗(yàn)多種相關(guān)演示方案。
目前,.NET Core 3.0 只部分支持托管 C++ 與 WinRT 互操作,完整的支持能力將在 .NET Core 3.1 當(dāng)中推出。
可空引用類型
C# 8.0 當(dāng)中引入了可空與不可空兩種新的引用類型,這意味著用戶可以對(duì)引用類型變量的屬性做出重要聲明:
某項(xiàng)引用不應(yīng)為空。當(dāng)變量不應(yīng)為空時(shí),則編譯器會(huì)強(qiáng)制執(zhí)行規(guī)則以確保安全地撤銷針對(duì)空變量的引用,而無(wú)需預(yù)先檢查引用目標(biāo)是否為空。
某項(xiàng)引用可以為空。當(dāng)變量可以為空時(shí),編譯器會(huì)強(qiáng)制執(zhí)行規(guī)則以確保您已經(jīng)對(duì)所引用的變量是否為空做出檢查。
相較于無(wú)法從引用變量的變量聲明當(dāng)中確定設(shè)計(jì)意圖的早期 C# 版本,此次發(fā)布的新功能具有明顯的優(yōu)勢(shì)。通過(guò)添加可空這一全新引用類型,您將能夠更明確地聲明自己的設(shè)計(jì)意圖,而編譯器則可以幫助您正確地完成這一目標(biāo)并及時(shí)發(fā)現(xiàn)代碼中的錯(cuò)誤。
接口成員的默認(rèn)實(shí)現(xiàn)
目前,一旦接口發(fā)布完畢,您將無(wú)法對(duì)其做出任何變更:換言之,要向其中添加新成員,我們就必然會(huì)對(duì)現(xiàn)有界面的實(shí)現(xiàn)成員造成破壞。
在 C# 8.0 當(dāng)中,大家可以為某一接口成員提供主體。結(jié)果就是,如果實(shí)現(xiàn)該接口的類沒(méi)有實(shí)現(xiàn)該成員(可能是因?yàn)榫帉懘a時(shí)還不存在該成員),那么調(diào)用代碼將只能獲得默認(rèn)的實(shí)現(xiàn)效果。
在本示例當(dāng)中,ConsoleLogger 類并不需要實(shí)現(xiàn)對(duì) ILogger 中的 Log(Exception) 重載,因?yàn)槠涫峭ㄟ^(guò)默認(rèn)實(shí)現(xiàn)進(jìn)行聲明的。現(xiàn)在,只要為現(xiàn)有實(shí)現(xiàn)成員提供默認(rèn)實(shí)現(xiàn),您就可以隨時(shí)向現(xiàn)有接口添加新的成員。
異步流
現(xiàn)在,您可以利用 IAsyncEnumerable 對(duì)異步數(shù)據(jù)流進(jìn)行 foreach。這一新的接口滿足了眾多開(kāi)發(fā)人員的長(zhǎng)久需求,也就是 IEnumerable 的異步版本。該語(yǔ)言允許大家對(duì)任務(wù)進(jìn)行 await foreach 以使用其元素。在產(chǎn)生方面,您的 yield return 條目可能會(huì)產(chǎn)生異步流。雖然聽(tīng)起來(lái)似乎比較復(fù)雜,但其實(shí)際上將在實(shí)踐當(dāng)中顯著簡(jiǎn)化操作。
以下示例展示了異步流的產(chǎn)生與使用情況。其中的 foreach 聲明為異步,其本身會(huì)利用 yield return 為調(diào)用程序產(chǎn)生一條異步流。這種利用 yield return 的模式亦是我們推出的異步流標(biāo)準(zhǔn)生產(chǎn)方式。
除了能夠?qū)崿F(xiàn) await foreach 之外,大家也可以創(chuàng)建出異步迭代器,例如一個(gè)能夠返回 IAsyncEnumerable/IAsyncEnumerator 并在其中同時(shí)實(shí)現(xiàn) await 與 yield return 的迭代器。對(duì)于需要處理的對(duì)象,您也可以使用能夠?qū)崿F(xiàn) Stream 以及 Timer 等多種框架類型的 IAsyncDisposable。
索引與范圍
我們還創(chuàng)建了新的語(yǔ)法與類型,可用于描述索引器、數(shù)組元素訪問(wèn)或者可以直接進(jìn)行數(shù)據(jù)訪問(wèn)的任何其他類型。其中包括對(duì)單一值(索引的通常定義)或者兩個(gè)值(描述范圍)的支持。
Index 是一種用于描述數(shù)組索引的新類型。您可以從通過(guò) int 從零開(kāi)始對(duì) Index 進(jìn)行計(jì)數(shù),也可以使用 ^ 前綴運(yùn)算符創(chuàng)建索引。在以下示例中,我們可以同時(shí)觀察到這兩種情況:
Range 的概念基本相同,其由兩個(gè) Index 值構(gòu)成,其一代表開(kāi)始、其二代表結(jié)束,且可以用 x…y 的范圍表達(dá)式編寫。接下來(lái),大家即可使用 Range 索引以生成底層數(shù)據(jù)的一個(gè)切片,具體如下所示:
使用聲明很多朋友可能已經(jīng)厭倦了使用那些要求縮進(jìn)代碼的語(yǔ)句,對(duì)吧?沒(méi)問(wèn)題,現(xiàn)在不會(huì)了。您可以按以下形式編寫代碼,該代碼將在當(dāng)前語(yǔ)句塊的作用域末尾添加 using 聲明,而后將對(duì)象放置在其末尾。
Switch 表達(dá)式
幾乎每一位 C# 用戶都非常喜歡 switch 語(yǔ)句的概念,但卻不太喜歡它的語(yǔ)法。C# 8 引入了 switch 表達(dá)式,該表達(dá)式可實(shí)現(xiàn)以下功能:
terser 語(yǔ)法
由于其屬于表達(dá)式,所以會(huì)返回一個(gè)值
與模式匹配全面集成
Switch 表達(dá)式中的關(guān)鍵字為“infix”,意味著該關(guān)鍵字位于測(cè)試值(在第一個(gè)示例中為 0)與示例列表之間,這種形式與 Lambda 表達(dá)式非常相似。
第一個(gè)示例對(duì)各方法使用了 Lambda 語(yǔ)法,該語(yǔ)法能夠與 switch 表達(dá)式良好集成,但并非必需。
在此示例中,共有兩種模式在發(fā)揮作用。首先,0 會(huì)與 Point 類型模式匹配,而后再與內(nèi)的屬性模式匹配。_ 用于描述丟棄模式,其與 switch 語(yǔ)句的默認(rèn)模式想再。
大家也可以更進(jìn)一步依賴元組解構(gòu)與參數(shù)位置,具體如下所示:
在本示例中,大家可以看到我們并不需要為每一種情況定義變量或者顯式類型。相反,編譯器可以將當(dāng)前正在測(cè)試的元組與已經(jīng)定義的元組進(jìn)行匹配。
所有這些模式,使得我們能夠編寫出意圖更加明確的聲明性代碼,而非單純執(zhí)行測(cè)試的過(guò)程代碼。編譯器能夠負(fù)責(zé)實(shí)現(xiàn)無(wú)聊的過(guò)程代碼,并保證其始終得到正確執(zhí)行。
當(dāng)然,在某些情況下,switch 語(yǔ)句的實(shí)際效果可能仍然優(yōu)于新的 switch 表達(dá)式與模式中的語(yǔ)法形式。
速度更快的 JSON API
.NET Core 3.0 當(dāng)中包含一個(gè)新的 JSON API 家族,其用于實(shí)現(xiàn) reader/writer 場(chǎng)景、利用文檔對(duì)象模型(DOM)實(shí)現(xiàn)隨機(jī)訪問(wèn)外加一個(gè)序列化程序。大家可能已經(jīng)非常熟悉如何使用 Json.NET 。新的 API 旨在滿足大多數(shù)同類場(chǎng)景需求,但內(nèi)存需求更低、執(zhí)行速度更快。
簡(jiǎn)而言之,我們希望構(gòu)建一個(gè)新的 JSON API,從而充分利用.NET Core 中的所有全新性能優(yōu)勢(shì),并以此為基礎(chǔ)全面提升性能水平。很明顯,我們不可能在保持現(xiàn)有代碼庫(kù)(例如 Jason.NET )兼容性的同時(shí)達(dá)成這一目標(biāo)。
下面,讓我們分層對(duì)這一新的 API 家族做出闡述。
Utf8JsonReader
System.Text.Json.Utf8JsonReader 是種面向面向 UTF-8 編碼 JSON 文本的高性能、低分配、純轉(zhuǎn)發(fā)讀取器,負(fù)責(zé)從 ReadOnlySpan 當(dāng)中讀取內(nèi)容。Utf8JsonReader 是一種基礎(chǔ)的低級(jí)類型,我們可以利用它構(gòu)建自定義解析器與解串器。利用新的 Utf8JasonReader,對(duì) JSON 負(fù)載的讀取速度將可達(dá)到以往 Json.NET 中讀取速度的兩倍。另外,除非大家需要將 JSON 令牌實(shí)現(xiàn)為(UTF16)字符串,否則其不會(huì)進(jìn)行分配。
Utf8JsonWriter
System.Text.Json.Utf8JsonWriter 提供一種高性能、非緩存、純轉(zhuǎn)發(fā)方式,可用于將 String、Int32 以及 DateTime 等常規(guī).NET 類型寫入為 UTF-8 編碼 JSON 文本。與 reader 類似,writer 是一種基礎(chǔ)低級(jí)類型,開(kāi)發(fā)人員可以利用它構(gòu)建自定義序列化程序。使用新的 Utf8JasonWriter,JSON 負(fù)載的編寫速度將比 Json.NET 寫入器高 30% 到 80%,且不進(jìn)行分配。
JsonDocument
System.Text.Json.JsonDocument 能夠?qū)?JSON 數(shù)據(jù)進(jìn)行解析,并建立只讀文檔對(duì)象模型(DOM)功能,用以查詢?cè)搶?duì)象以支持隨機(jī)訪問(wèn)與枚舉。其建立在 Utf8JasonReader 基礎(chǔ)之上,組成數(shù)據(jù)的 JSON 元素可以通過(guò)由 JsonDocument 類型(被稱為 RootElement 屬性)公開(kāi)的 JsonElement 類型進(jìn)行訪問(wèn)。JsonElement 當(dāng)中包含 JSON 數(shù)組與對(duì)象枚舉器,外加用于將 JSON 文本轉(zhuǎn)換為常見(jiàn).NET 類型的 API。利用 JsonDocument,對(duì)常規(guī) JSON 負(fù)載進(jìn)行解析并訪問(wèn)其中各成員的速度,一般可以達(dá)到以往 Json.NET 的 2 到 3 倍;而且由于數(shù)據(jù)本身大小合理(小于 1 MB),因此幾乎不需要進(jìn)行數(shù)據(jù)分配。
JSON 序列化器
System.Text.Json.JsonSerializer 層位于高性能 Utf8JsonReader 與 Utf8JsonWriter 之上。其負(fù)責(zé)對(duì)來(lái)自 JSON 的對(duì)象進(jìn)行反序列化,并對(duì)指向 JSON 的對(duì)象進(jìn)行序列化。內(nèi)存分配得到嚴(yán)格控制,同時(shí)支持利用 Stream 以異步方式進(jìn)行 JSON 讀取與寫入。
引入全新 SqlClient
SqlClient 是一款數(shù)據(jù)提供程序,您可以利用它直接利用 ADO .NET API 訪問(wèn)微軟 SQL Server 以及 Azure SQL Database 等。SqlClient 已經(jīng)正式發(fā)布,并通過(guò) Microsoft.Data.SqlClient NuGet 工具包進(jìn)行更新,且同時(shí)支持 .NET Freamework 與 .Net Core 應(yīng)用程序。通過(guò)使用 NuGet,SQL 團(tuán)隊(duì)將能夠更輕松地為 Freamework 與 .Net Core 用戶提供更新。
ARM 與物聯(lián)網(wǎng)支持
我們?cè)诒敬伟l(fā)行版當(dāng)中實(shí)現(xiàn)了對(duì) Linux ARM64 的支持,這也是對(duì)此前 .NET Core 2.1 與 2.2 版本當(dāng)中面向 Linux 與 Windows 提供 ARM32 支持能力的延續(xù)。雖然某些物聯(lián)網(wǎng)工作負(fù)載能夠發(fā)揮我們現(xiàn)有 x64 功能提供的優(yōu)勢(shì),但仍有不少用戶強(qiáng)烈要求發(fā)布 ARM 支持功能。現(xiàn)在這一功能已經(jīng)落實(shí)到位,我們也在與計(jì)劃進(jìn)行大規(guī)模部署的客戶開(kāi)展廣泛合作。
不少利用.NET 的物聯(lián)網(wǎng)部署場(chǎng)景涉及邊緣設(shè)備,且完全面向網(wǎng)絡(luò)。其他一些場(chǎng)景則要求對(duì)硬件進(jìn)行直接訪問(wèn)。在本次發(fā)行版中,我們添加了新的功能以在 Linux 上使用串行端口,同時(shí)可利用 Raspberry Pi 等設(shè)備上的數(shù)字引腳功能。該引腳使用多項(xiàng)協(xié)議。我們還添加了對(duì) GPIO、PWM、I2C 以及 SPI 的支持,以支持讀取傳感器數(shù)據(jù)、以無(wú)線方式交互并將文本與圖像輸出至顯示器等功能。
此功能屬于以下軟件包中的組成部分:
System.Device.Gpio
Iot.Device.Bindings
作為 GPIO(及其他同類協(xié)議)支持的一部分,我們審視了以往版本中的原有元素。我們發(fā)現(xiàn)其中的 C# 與 Python API,在這兩種場(chǎng)景下 API 都屬于原生庫(kù)上的打包器,而這些庫(kù)則采用 GPL 許可。我們認(rèn)為這種方法缺乏可持續(xù)性。因此,我們構(gòu)建了 100% 純 C# 解決方案以實(shí)現(xiàn)這些協(xié)議,這意味著我們的 API 可以在支持 .NET Core 的任何環(huán)境下運(yùn)作,利用 C# 調(diào)試器(通過(guò) sourcelink)進(jìn)行調(diào)試,并支持多種底層 Linux 驅(qū)動(dòng)程序(包括 sysfs、libgpoid 以及其它針對(duì)特定主板的驅(qū)動(dòng)程序)。所有代碼皆遵循 MIT 許可。與現(xiàn)有技術(shù)相比,我們認(rèn)為這種新方法將給.NET 開(kāi)發(fā)人員帶來(lái)巨大的便利。
.NET Core 運(yùn)行時(shí)前滾策略更新
現(xiàn)在,.NET Core 運(yùn)行時(shí)(更具體地講,運(yùn)行時(shí)綁定程序)開(kāi)始提供主版本的前滾選擇策略。運(yùn)行時(shí)綁定程序?qū)⒛J(rèn)啟用面向補(bǔ)丁與次版本的前滾功能。我們決定公開(kāi)一組更為廣泛的策略,以幫助開(kāi)發(fā)人員快速恢復(fù)可能存在的更新問(wèn)題,但原有前滾操作并不受影響。
我們發(fā)布了一項(xiàng)名為 RollForward 的新屬性,該屬性能夠接受以下值:
LatestPatch——前滾至最新補(bǔ)丁版本。其會(huì)禁用 Minor 策略。
Minor ——前滾至最早次版本以解決所需次版本缺失問(wèn)題。如果該次版本存在,則 LatesPatch 策略即可起效。這也是系統(tǒng)中采用的默認(rèn)策略。
Major ——前滾至最早主版本與最早次版本,以解決所需主版本缺失問(wèn)題。如果該主版本存在,則隨后使用 Minor 策略。
LatestMinor——前滾至最新次版本,即使存在所請(qǐng)求的次版本亦不受影響。
LatestMajor ——前滾至最新主版本,即使存在所請(qǐng)求的主版本亦不受影響。
Disable ——不進(jìn)行前滾。僅綁定至指定版本。我們不建議大家在常規(guī)用途中使用這一選項(xiàng),因?yàn)槠鋾?huì)禁用前滾至最新補(bǔ)丁后版本的功能。僅建議您在測(cè)試環(huán)境中使用。
Docker 與 cgroup 限制
很多開(kāi)發(fā)人員都在利用容器技術(shù)打包并運(yùn)行自己的應(yīng)用程序。其中的一大重要問(wèn)題,在于容器的 CPU 或者內(nèi)存等資源可能受到限制。我們?cè)缭?2017 年就實(shí)現(xiàn)了對(duì)內(nèi)存限制功能的支持,遺憾的是,我們發(fā)現(xiàn)該實(shí)現(xiàn)的主動(dòng)性不足以將容器環(huán)境以可靠方式保持在配置限制之下,意味著即使設(shè)置了內(nèi)存限制(特別是小于 500 MB 的情況),應(yīng)用程序仍然有可能出現(xiàn) OOM 問(wèn)題。我們已經(jīng)在 .NET Core 3.0 當(dāng)中修復(fù)了這一問(wèn)題。這一改進(jìn)意義重大,我們強(qiáng)烈建議使用 .NET Core Docker 的用戶升級(jí)至 .NET Core 3.0。
Docker 資源限制功能構(gòu)建在 cgroup 基礎(chǔ)之上,而 cgroup 又是一項(xiàng) Linux 內(nèi)核功能。從運(yùn)行時(shí)的角度來(lái)看,我們需要以 cgroup 基元為目標(biāo)。
大家可以利用 docker run -m 參數(shù)來(lái)限制容器的可用內(nèi)存,如下所示,此示例用于創(chuàng)建一個(gè)基于 Alpine 且內(nèi)存容量為 4 MB 的容(而后輸出內(nèi)存限制):
我們還添加了新的變更,以更好地支持 CPU 限制(–cpus)。其中包括更新運(yùn)行時(shí)對(duì)十進(jìn)制 CPU 值進(jìn)行四舍五入的方式。如果將—cpus 設(shè)置為(足夠)接近某個(gè)較小的整數(shù)(例如 1.499999999)的值,則運(yùn)行時(shí)會(huì)對(duì)該值進(jìn)行四舍五入(這種情況下將四舍五入為 1)。結(jié)果就是,運(yùn)行時(shí)所使用的 CPU 數(shù)量低于需求,從而導(dǎo)致 CPU 資源不足。通過(guò)對(duì)該值進(jìn)行直接進(jìn)位,運(yùn)行時(shí)在理論上會(huì)增加 OS 線程調(diào)度程序的壓力,但即使是在最極端的情況下(–cpus=1.000000001,以往 其會(huì)被四舍五入為 1,但現(xiàn)在會(huì)直接進(jìn)位為 2),我們也沒(méi)有發(fā)現(xiàn) CPU 出現(xiàn)任何性能下降。
下一步是確保線程池遵循 CPU 限制。線程池算法中有一部分負(fù)責(zé)計(jì)算 CPU 的繁忙時(shí)間,也就是計(jì)算可用 CPU 容量。通過(guò)在計(jì)算 CPU 繁忙時(shí)間當(dāng)中考慮 CPU 限制,我們得以避免線程池在爭(zhēng)用中執(zhí)行的各種試探操作:一種方法可能嘗試分配更多線程以增加 CPU 繁忙時(shí)間;但另一種方法則可能嘗試分配更少線程,以避免不必要的線程浪費(fèi)。
默認(rèn)情況下降低 GC 堆大小
在致力于改善對(duì) docker 內(nèi)存限制支持能力的同時(shí),我們也受到了啟發(fā),并著手對(duì)通用 GC 策略加以更新,旨在為更為廣泛的應(yīng)用程序的內(nèi)存使用率帶來(lái)改善(即使未運(yùn)行在容器之內(nèi))。這些變更使得第 0 代預(yù)算分配能夠更好地與現(xiàn)代處理器的緩存大小及緩存層級(jí)保持一致。
我們的團(tuán)隊(duì)成員 Damian Edwards 注意到,ASP.NET 基準(zhǔn)測(cè)試的內(nèi)存使用量減少了一半,但其它性能指標(biāo)并未出現(xiàn)任何負(fù)面影響。這是一項(xiàng)驚人的進(jìn)步!如他所言,這些將成為新的默認(rèn)設(shè)置,且不需要對(duì)您的代碼做出任何修改(只需采用 .NET Core 3.0 即可)。
當(dāng)然,我們?cè)?ASP.NET 基準(zhǔn)測(cè)試中觀察到的內(nèi)存節(jié)約效果,可能代表 / 不代表您的實(shí)際體驗(yàn)。我們希望聽(tīng)到更多朋友在實(shí)際應(yīng)用程序內(nèi)存使用量方面觀察到的結(jié)果。
改善對(duì)多處理器設(shè)備的支持能力
基于 .NET 的 Windows 傳統(tǒng),GC 需要配合 Windows 處理器組概念才能支持包含 64 塊以上處理器的計(jì)算機(jī)。這一實(shí)現(xiàn)早在 5 到 10 年前的 .NET Framework 當(dāng)中即已完成。但利用 .NET Core,我們最初選擇了 Linux PAL 以實(shí)現(xiàn)類似的概念——雖然 Linux 當(dāng)中不存在這一原生概念。此后,我們?cè)?GC 當(dāng)中放棄了這一概念,并將其轉(zhuǎn)化為 Windows APL。
GC 現(xiàn)在公開(kāi)了一個(gè)配置開(kāi)關(guān),即 GCHeapAffinitizeRanges,用于在包含 64 個(gè)以上處理器的計(jì)算機(jī)上指定相似的掩碼。
GCLarge Page 支持
Large Pages 或者叫 Huge Pages 是一項(xiàng)功能,操作系統(tǒng)可利用其構(gòu)建起大于原生頁(yè)面大小(通常為 4K)的內(nèi)存區(qū)域,從而提高調(diào)用這些大頁(yè)面的應(yīng)用程序的性能表現(xiàn)。
當(dāng)發(fā)生虛擬到物理地址的轉(zhuǎn)換時(shí),系統(tǒng)會(huì)首先查詢(通常為并行)被稱為轉(zhuǎn)換后備緩沖區(qū)(TLB)的高速緩存,以檢查是否存在可用于所訪問(wèn)虛擬地址的可用物理翻譯,以避免進(jìn)行可能占用大量資源的頁(yè)面移動(dòng)操作。每個(gè)大頁(yè)面翻譯都需要使用 CPU 內(nèi)部的一個(gè)翻譯緩沖區(qū)。該緩沖區(qū)的大小通常要比本地頁(yè)面大三個(gè)數(shù)量級(jí);這能夠極大提高轉(zhuǎn)換緩沖區(qū)的效率,從而改善內(nèi)存在頻繁訪問(wèn)下的性能。在具有雙層 TLB 的虛擬機(jī)當(dāng)中,這一改進(jìn)顯得尤為重要。
GC 現(xiàn)在能夠利用 GCLargePages 選項(xiàng)功能進(jìn)行配置,從而選擇在 Windows 上分配大頁(yè)面。利用大頁(yè)面能夠減少 TLB 遺漏,進(jìn)而在總體上提高應(yīng)用程序的性能;但是,這項(xiàng)功能也有著自己的局限,應(yīng)當(dāng)認(rèn)真考量。Bing.com 就采用了這項(xiàng)功能,并切實(shí)獲得了性能提升。
.NET Core 版本 API
我們?cè)?NET Core 3.0 當(dāng)中對(duì).NET Core 版本 API 做出改進(jìn),現(xiàn)在它們能夠返回您所需要的版本信息。這些變更雖然在客觀上帶來(lái)了便利,但卻存在技術(shù)破壞性,而且有可能影響到依賴現(xiàn)有版本 API 獲取各類信息的應(yīng)用程序。
現(xiàn)在,大家可以訪問(wèn)以下版本信息:
Event Pipe 改進(jìn) Event Pipe 現(xiàn)在支持多個(gè)會(huì)話。這意味著大家可以使用 EventListener 在進(jìn)程內(nèi)使用事件,同時(shí)獲得進(jìn)程外 event pipe 客戶端。
添加了新的 Perf Counters:
GC 中的時(shí)間百分比
Gen 0 堆大小
Gen 1 堆大小
Gen 2 堆大小
LOH 堆大小
分配率
加載組件數(shù)量
ThreadPool 線程數(shù)量
鎖定爭(zhēng)用率
ThreadPool 工作條目隊(duì)列
ThreadPool 已完成工作項(xiàng)比例
現(xiàn)在,大家可以使用同樣的 Event Pipe 基礎(chǔ)設(shè)施實(shí)現(xiàn) Profiler 險(xiǎn)別。
HTTP/2 支持
現(xiàn)在,我們?cè)?HttpClinet 當(dāng)中支持 HTTP/2。采用新協(xié)議是為了滿足某些 API 的要求,例如 gRPC 與 Apple Push Notification Service。我們希望未來(lái)會(huì)有更多服務(wù)使用 HTTP/2 協(xié)議。此外,ASP.NET 也同樣支持 HTTP/2。
備注:首選 HTTP 協(xié)議版本將通過(guò) TLS/ALPN 協(xié)商,并僅在服務(wù)器選擇使用 HTTP/2 時(shí)才加以使用。
分層編譯
分層編譯是 .NET Core 2.1 中的一項(xiàng)可選功能,該功能使得運(yùn)行時(shí)能夠更靈活地使用即時(shí)(JIT)編譯器,從而在啟動(dòng)時(shí)獲得更佳性能并最大程度提升吞吐量。.NET Core 3.0 在默認(rèn)情況下即啟用這一功能。去年,我們對(duì)該功能做出了一系列改進(jìn),包括針對(duì)各類工作負(fù)載(例如網(wǎng)站、PowerShell 以及 Windows 桌面應(yīng)用程序)進(jìn)行測(cè)試。性能確實(shí)迎來(lái)顯著提升,因此我們決定將其作為默認(rèn)選項(xiàng)。
IEEE 浮點(diǎn)改進(jìn)
我們對(duì)浮點(diǎn) API 進(jìn)行了更新,以符合 IEEE 754-2008 修訂版的要求。.NET Core 浮點(diǎn)項(xiàng)目的目標(biāo),在于公開(kāi)所有“必要”運(yùn)算,以確保其在行為層面符合 IEEE 提出的規(guī)范。
解析與格式化修復(fù):
正確解析并舍入任何長(zhǎng)度的輸入。
正確解析并格式化負(fù)零。
通過(guò)進(jìn)行不區(qū)分大小寫的檢查,并在適用時(shí)允許使用可選前置 + 以正確解析無(wú)限與 NaN。
新的 Math API:
BitIncrement/BitDecrement ——對(duì)應(yīng)于 nextUp 與 nextDown IEEE 運(yùn)算。二者分別返回大于或者小于輸入內(nèi)容的最小浮點(diǎn)數(shù)。例如,Math.BitIncrement(0.0)將返回 double.Epsilon。
MaxMagnitude/MinMagnitude——對(duì)應(yīng)于 maxNumMag 與 minNumMag IEEE 運(yùn)算,二者分別返回大于或者小于輸入內(nèi)容的值。例如,Math.MaxMagnitude(2.0 -3.0) 將返回 -3.0。
ILogB ——對(duì)應(yīng)于 logB IEEE 運(yùn)算,該運(yùn)算將返回一個(gè)整數(shù)值,且該值為輸入?yún)?shù)的以 2 為底的整數(shù)對(duì)數(shù)。實(shí)際上與 floor(log2(x)) 相同,但舍入誤差最小。
ScaleB——對(duì)應(yīng)于采用整數(shù)值的 scaleB IEEE 運(yùn)算,其相當(dāng)于返回 x * pow(2,n) 的值,但舍入誤差最小。
Log2——對(duì)應(yīng)于 log2 IEEE 運(yùn)算,返回以 2 為底的對(duì)數(shù),且舍入誤差最小。
FusedMultiplyAdd ——對(duì)應(yīng)于 fma IEEE 運(yùn)算,負(fù)責(zé)執(zhí)行積和熔加運(yùn)算。具體而言,其通過(guò)一次運(yùn)算完成(xy)+ z 運(yùn)算,同時(shí)使舍入誤差最小。以 FusedMultiplyAdd (1e308, 2.0, -1e308) 為例,其返回值為 1e308。常規(guī)(1e308
2.0)-1e308 將返回 double.PositiveInfinity。
CopySign ——對(duì)應(yīng)于 copySign IEEE 運(yùn)算,其返回 x 的值,但同時(shí)帶有 y 符號(hào)。
.NET 平臺(tái)相關(guān)改進(jìn)
我們添加了一些新的 API,用以訪問(wèn)某些面向性能的 CPU 指令,包括 SIMD 或 Bit Manipulation 指令集。這些指令能夠在某些場(chǎng)景下實(shí)現(xiàn)巨大的性能提升,例如更高效地并行處理數(shù)據(jù)。除了公開(kāi)這些可供應(yīng)用程序使用的 API 之外,我們還開(kāi)始利用相關(guān)指令對(duì).NET 庫(kù)進(jìn)行提速。
以下 CoreCLR PRs 通過(guò)實(shí)現(xiàn)或者使用的方式展示了一部分內(nèi)部函數(shù):
實(shí)現(xiàn)簡(jiǎn)單 SSE2 硬件內(nèi)部函數(shù)
實(shí)現(xiàn) SSE 硬件內(nèi)部函數(shù)
Arm64 Base 硬件內(nèi)部函數(shù)
面向 LocateFound使用 TZCNT 與 LZCNT
現(xiàn)可在 Linux 上支持 TLS 1.3 與 OpenSSL 1.1.1
.NET Core 現(xiàn)在能夠利用 OpenSSL 1.1.1 中的 TLS 1.3 支持能力。TLS 1.3 能夠?yàn)?OpenSSL 團(tuán)隊(duì)提供多項(xiàng)優(yōu)勢(shì):
通過(guò)減少客戶端與服務(wù)器間的往返次數(shù)縮短連接時(shí)長(zhǎng)。
通過(guò)消除各種過(guò)時(shí)及不安全的加密算法、同時(shí)加密更多連接握手,以提高安全性。
.NET Core 3. 能夠利用 OpenSSL 1.1.1、OpenSSL 1.1.0 以及 OpenSSL 1.0.2(以及您能夠在 Linux 系統(tǒng)上找到任何最佳版本)。如果客戶端與服務(wù)器均支持 TLS 1.3,且 OpenSSL 1.1.1 可用,則 SslStream 與 HttpClinet 類型將在使用 SslProtocols.None 時(shí)選擇 TLS 1.3(系統(tǒng)默認(rèn)協(xié)議)。
.NET Core 后續(xù)還將在 Windows 與 MacOS 上支持 TLS 1.3——預(yù)計(jì)以自動(dòng)化方式實(shí)現(xiàn),敬請(qǐng)期待。
加密
我們?cè)黾恿藢?duì) AES-GCM 以及 AES-CCM 加密機(jī)制的支持,這些加密算法將通過(guò) System.Security.Cryptography.AesGcm 與 System.Security.Cryptography.AesCcm 實(shí)現(xiàn)。這些算法皆屬于帶關(guān)聯(lián)數(shù)據(jù)的加密認(rèn)證(AEAD)算法,同時(shí)也是首批被添加至 .NET Core 當(dāng)中的驗(yàn)證加密(AE)算法。
.NET Core 3.0 現(xiàn)在支持通過(guò)標(biāo)準(zhǔn)格式導(dǎo)入及導(dǎo)出非對(duì)稱公鑰與私鑰,且無(wú)需使用 X.509 證書。
所有密鑰類型(RSA、DSA、ECDsa、ECDiffieHellman)都支持 X.509 SubjectPublicKeyInfo 格式的公鑰,以及 PKCS#8 PrivateKeyInfo 與 PKCS#8 EncryptedPrivateKeyInfo 格式的私鑰。此外,RSA 還支持 PKCS#1 RSAPublicKey 與 PKCS#1 RSAPrivateKey。所有導(dǎo)出方法皆產(chǎn)生 DER 編碼的二進(jìn)制數(shù)據(jù),而導(dǎo)入方法也基本相同;如果某一密鑰以文本友好的 PEM 格式存儲(chǔ),則調(diào)用程序?qū)⑿枰葘?duì)內(nèi)容進(jìn)行 base64 解碼,而后才能進(jìn)行方法導(dǎo)入。
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)行檢查與修改。
支持新的日本年號(hào)(令和)
2019 年 5 月 1 日,日本開(kāi)始使用新的年號(hào)——令和。因此,支持日語(yǔ)日歷的軟件(例如 .NET Core)必須進(jìn)行更新以支持這一新年號(hào)。.NET Core 與 .NET Framework 已經(jīng)更新,現(xiàn)在可以正確處理新年號(hào)下的日文日期格式與解析結(jié)果。
.NET 依賴于操作系統(tǒng)或其他更新以正確處理令和日期。如果您或者您的客戶使用 Windows 系統(tǒng),請(qǐng)下載 Windows 版本的最新更新。如果您運(yùn)行的是 MacOS 或者 Linux,請(qǐng)下載并安裝支持日本新年號(hào)的 ICU 64.2 版本。
Assembly Load Context 改進(jìn)
關(guān)于 AssemblyLoadContext 的改進(jìn):
實(shí)現(xiàn)上下文命名
添加 ALC 枚舉功能
對(duì) ALC 內(nèi)程序集進(jìn)行枚舉的功能
實(shí)現(xiàn)類型具體化——旨在簡(jiǎn)化實(shí)例化(簡(jiǎn)單場(chǎng)景不需要自定義類型)
通過(guò)將 AssemblyDependencyResolyer 與自定義 AssemblyLoadContext 加以結(jié)合,應(yīng)用程序?qū)⒛軌蛟诩虞d插件的過(guò)程中,從各個(gè)正確位置加載該插件所需要的依賴項(xiàng),且某一插件的依賴項(xiàng)不會(huì)與其他插件的依賴項(xiàng)發(fā)生沖突。
Assembly 可卸載性
Assembly 的可制裁性是 AssemblyLoadContext 中提供的一項(xiàng)新功能。從 API 的角度來(lái)看,這項(xiàng)新功能具有極高的透明度,且面向部分新 API 公開(kāi)。其允許開(kāi)發(fā)人員對(duì)加載程序的上下文進(jìn)行卸載,從而釋放原本被實(shí)例化類型、靜態(tài)字段以及程序集本身所占用的內(nèi)存。應(yīng)用程序可以通過(guò)這種機(jī)制實(shí)現(xiàn)程序集的永久加載與卸載,且不會(huì)引發(fā)內(nèi)存泄漏。
我們希望這項(xiàng)新功能被用于以下場(chǎng)景:
需要?jiǎng)討B(tài)插件加載與卸載的插件使用場(chǎng)景。
對(duì)代碼的動(dòng)態(tài)編譯、運(yùn)行以及刷新。適用于網(wǎng)站、腳本引擎等。
加載程序集以進(jìn)行自我檢查(例如 ReflectionOnlyLoad),但在大多數(shù)情況下 MetadataLoadContext 仍然是更好的選擇。
利用 MetadataLoadContext 讀取 Assembly 元數(shù)據(jù)
我們添加了 MetadataLoadContext,希望在不影響調(diào)用程序域的前提下讀取 assembly 元數(shù)據(jù)。各 assembly 這以數(shù)據(jù)的形式讀取,其中包括與當(dāng)前運(yùn)行時(shí)環(huán)境不同的各類架構(gòu)及平臺(tái)上的 assembly。MetadataLoadContext 與 ReflectionOnlyLoad 存在一定交集,但后者僅適用于 .NET Framework。
MetdataLoadContext 目前通過(guò) System.Reflection.MetadataLoadContext 軟件包發(fā)布,其屬于 .NET Standard 2.0 軟件包。
MetadataLoadContext 的適用場(chǎng)景包括設(shè)計(jì)時(shí)功能、構(gòu)建時(shí)工具與運(yùn)行時(shí)點(diǎn)亮功能等需要將一組 assembly 作為數(shù)據(jù)進(jìn)行檢查,并在執(zhí)行檢查后釋放所有文件鎖與內(nèi)存的場(chǎng)景。
Native Hosting 示例
.NET Core 團(tuán)隊(duì)還發(fā)布了一個(gè) Native Hosting 示例,其中展示了在本機(jī)應(yīng)用程序當(dāng)中托管 .NET Core 的相關(guān)最佳實(shí)踐。
作為 .NET Core 3.0 中的組成部分,我們現(xiàn)在面向 .NET Core 本地主機(jī)公開(kāi)了這一原本只通過(guò)官方 .NET Core 主機(jī)為 .NET Core 托管應(yīng)用程序提供的功能。此項(xiàng)功能主要與 assembly 加載相關(guān),利用這項(xiàng)功能可幫助大家更輕松地構(gòu)建能夠利用 .NET Core 完整功能集的本地主機(jī)。
其他 API 改進(jìn)
我們?cè)?.NET Core 2.1 版本當(dāng)中對(duì) Span、Memory 以及其他相關(guān)類型做出優(yōu)化。現(xiàn)在,span construction、切片、解析以及格式化等常規(guī)操作的執(zhí)行效果將有所提升。此外,String 等類型也得到了明顯改進(jìn),能夠在與 Dictionary 及其他集合共同充當(dāng)鍵時(shí)擁有更好的執(zhí)行效率。所有改進(jìn)開(kāi)箱即用,無(wú)需對(duì)您的代碼做出任何變更。
下面來(lái)看其它最新改進(jìn):
Brotli 內(nèi)置 HttpClient 支持能力
ThreadPool.UnsafeQueueWorkItem(IThreadPoolWorkItem)
Unsafe.Unbox
CancellationToken.Unregister
復(fù)雜算術(shù)運(yùn)算符
Socket APIs for TCP 仍然有效
StringBuilder.GetChunks
IPEndPoint 解析
RandomNumberGenerator.GetInt32
System.Buffers.SequenceReader
默認(rèn)情況下,應(yīng)用程序現(xiàn)在具有原生可執(zhí)行文件
.NET Core 應(yīng)用程序現(xiàn)在擁有自己的原生可執(zhí)行文件。對(duì)于依賴框架的應(yīng)用程序而言,這是一項(xiàng)前所未有的新功能。在此之前,只有獨(dú)立應(yīng)用程序具有可執(zhí)行文件。這些新的可執(zhí)行文件,將在效果上與此前的原生可執(zhí)行文件保持一致:
您可以雙擊可執(zhí)行文件以啟動(dòng)對(duì)應(yīng)應(yīng)用程序。
您可以在 Windows 上使用 myapp.exe,或者在 Linux 及 MacOS 上使用./myapp 通過(guò)命令提示符啟動(dòng)應(yīng)用程序。
作為 build 的組成部分,新生成的可執(zhí)行文件將與您的操作系統(tǒng)以及 CPU 相匹配。例如,如果您使用的是 Linux x64 計(jì)算機(jī),那么可執(zhí)行文件將僅可在該類型的計(jì)算機(jī)上運(yùn)行——無(wú)法在 Windows 以及 Linux ARM 計(jì)算機(jī)上運(yùn)行。這是因?yàn)榭蓤?zhí)行文件使用本機(jī)代碼(例如 C++)。如果要定位為其他機(jī)器類型,則需要在發(fā)布時(shí)使用對(duì)應(yīng)的運(yùn)行時(shí)參數(shù)。如果愿意,您也可以繼續(xù)使用 dotnet 命令啟動(dòng)應(yīng)用程序,而不使用原生可執(zhí)行文件。
利用 ReadyToRun 鏡像優(yōu)化 .NET Core 應(yīng)用
通過(guò)將應(yīng)用程序 assemblies 編譯為 ReadyToRun(R2R)格式,可以改進(jìn) .NET Core 應(yīng)用程序的啟動(dòng)速度。R2R 是一種提前(AOT)編譯格式,在 .NET Core 3.0 版本中以可選功能的形式提供。
R2R 二進(jìn)制文件能夠減少應(yīng)用程序加載時(shí) JIT 需要完成的工作量,從而提高啟動(dòng)性能。二進(jìn)制文件當(dāng)中包含與 JIT 產(chǎn)生的代碼相似的本機(jī)代碼,能夠通過(guò)分擔(dān) JIT 的負(fù)載壓力帶來(lái)更理想的啟動(dòng)性能。R2R 二進(jìn)制文件體積較大,因?yàn)槠渲屑劝虚g語(yǔ)言(IL)代碼(某些情況下仍然需要此代碼),同時(shí)包含同一代碼的本機(jī)版本,用以改善啟動(dòng)速度。
要啟用 R2R 編譯:
將 PublishReadyToRun 屬性設(shè)置為 true。
使用 RuntimeIdentifie 顯式參數(shù)發(fā)布。
備注:在編譯應(yīng)用程序 assemblies 時(shí),生成的本機(jī)代碼將特定于當(dāng)前平臺(tái)與架構(gòu)(因此,大家在發(fā)布時(shí)必須指定有效的 RuntimeIdentifier)。
以下為具體示例:
使用以下命令進(jìn)行發(fā)布:
備注:RuntimeIdentifier 可設(shè)置為其他操作系統(tǒng)或者芯片類型,亦可在項(xiàng)目文件內(nèi)進(jìn)行設(shè)置。
Assembly Linking
.NET core 3.0 SDK 附帶一款工具,可通過(guò)分析 IL 與修剪未使用的 assemblies 以降低應(yīng)用程序的體積。這是 .NET Core 3.0 中的另一項(xiàng)發(fā)行時(shí)可選功能。
在 .NET Core 當(dāng)中,我們可以隨時(shí)發(fā)布包含代碼運(yùn)行所需的一切元素的自包含應(yīng)用程序,而無(wú)需在部署目標(biāo)上安裝 .NET。在某些情況下,該應(yīng)用僅需要框架中的一小部分即可運(yùn)行,因此修剪掉不必要的框架部分能夠有效降低應(yīng)用程序體積。我們利用 IL linker 對(duì)應(yīng)用程序的 IL 進(jìn)行掃描,從而檢測(cè)出哪些代碼確有必要,而后對(duì)未使用的框架庫(kù)進(jìn)行修剪。這能夠顯著降低某些應(yīng)用程序的體積。一般來(lái)講,小型工具控制臺(tái)類應(yīng)用程序的瘦身效果最為明顯,因?yàn)槠渫ǔJ褂每蚣苤械妮^小子集,且調(diào)整難度更低。
要使用 linker 工具:
將 PublishTrimmed 的屬性設(shè)置為 true。
將 RuntimeIdentifier 作為顯式參數(shù)進(jìn)行發(fā)布。
以下為相關(guān)示例:
使用以下命令進(jìn)行發(fā)布:
備注:RuntimeIdentifier 可設(shè)置為其他操作系統(tǒng)或者芯片類型,亦可在項(xiàng)目文件內(nèi)進(jìn)行設(shè)置。
根據(jù)應(yīng)用程序代碼的實(shí)際調(diào)用情況,所發(fā)布的輸出結(jié)果將包含框架庫(kù)中的一個(gè)子集。對(duì)于最簡(jiǎn)單的 helloworld 應(yīng)用,linker 工具能夠?qū)?yīng)用程序體積縮小 68 MB 到 28 MB。
在修剪之后,需要使用反射或者相關(guān)動(dòng)態(tài)功能的應(yīng)用程序或者框架(包括 ASP .NET Core 以及 WPF)通常無(wú)法正常執(zhí)行,這是因?yàn)?linker 無(wú)法識(shí)別這種動(dòng)態(tài)行為,因此一般不能確定反射操作在運(yùn)行時(shí)中需要的框架類型。要修剪這類應(yīng)用程序,大家需要告知 linker 相關(guān)代碼當(dāng)中所依賴的各類工具包或框架以及各種相關(guān)信息類型。請(qǐng)確保您在修剪之后對(duì)應(yīng)用程序進(jìn)行全面測(cè)試,我們也正在 .NET 5 當(dāng)中對(duì)這一體驗(yàn)做出改進(jìn)。
關(guān)于 IL Linker 的更多細(xì)節(jié)信息,請(qǐng)參閱說(shuō)明文檔或者訪問(wèn) mono/linker 庫(kù)。
備注:在 .NET Core 之前的版本當(dāng)中,ILLink Tasks 以外部 NuGet 軟件包的形式提供,其中包含多種相同功能。但相關(guān)軟件包現(xiàn)已不再受到支持,請(qǐng)更新至 .NET Core 3.0 SDK 以獲取我們?yōu)槟鷾?zhǔn)備的全新體驗(yàn).
Linker 與 R2R 編譯器可同時(shí)作用于一款應(yīng)用程序。一般來(lái)講,Linker 能夠使您的應(yīng)用程序體積更小,而 R2R 則能夠再次恢復(fù)其體積,并在性能上帶來(lái)顯著提升。大家可以在各種配置當(dāng)中進(jìn)行測(cè)試,以了解各個(gè)選項(xiàng)帶來(lái)的具體影響。
發(fā)布單文件可執(zhí)行文件
現(xiàn)在,大家可以利用 dotnet publish 命令發(fā)布單文件可執(zhí)行文件了。這種形式的單一 EXE 實(shí)際上是一個(gè)自解壓可執(zhí)行文件,其中以資源形式包含所有依賴項(xiàng)(包括本地依賴項(xiàng))。在啟動(dòng)時(shí),它會(huì)將所有依賴項(xiàng)復(fù)制到某個(gè)臨時(shí)目錄,通過(guò)該目錄進(jìn)行加載。依賴項(xiàng)只需要解壓一次,后續(xù)啟動(dòng)將速度極快,不再存在任何性能損失。
大家可以通過(guò)在項(xiàng)目文件中添加 PublishSingleFile 屬性,或者在命令行中添加新開(kāi)關(guān)的方式啟用這一發(fā)布選項(xiàng)。
要生成獨(dú)立的單 EXE 應(yīng)用程序,以下示例為 64 位 Windows 系統(tǒng)下的命令:
備注:RuntimeIdentifier 可設(shè)置為其他操作系統(tǒng)或者芯片類型,亦可在項(xiàng)目文件內(nèi)進(jìn)行設(shè)置。
若需了解更多細(xì)節(jié)信息,請(qǐng)參閱單文件捆綁器說(shuō)明文檔。
Assembly 修剪器、提前編譯(通過(guò) crossgen)以及單文件捆綁功能皆為 .NET Core 3.0 中提供的全新選項(xiàng),大家可以根據(jù)需求獨(dú)立使用或者以組合方式使用。相信一部分用戶可能喜愛(ài)通過(guò)提前編譯器提供的單 exe 發(fā)布選項(xiàng),而非我們?cè)?NET Core 3.0 當(dāng)中提供的自解壓可執(zhí)行文件方法。.NET 5 發(fā)行版當(dāng)中將正式提供提前編譯器方法。
dotnet build 現(xiàn)在可復(fù)制依賴項(xiàng)
dotnet build 現(xiàn)在能夠在 build 操作過(guò)程當(dāng)中,將應(yīng)用程序中的 NuGet 依賴項(xiàng)從 NuGet 緩存復(fù)制到 build 輸出文件夾內(nèi)。在此版本之前,各依賴項(xiàng)僅能作為 dotnet publish 中的一部分進(jìn)行復(fù)制。此次變更使您能夠利用 xcopy 將 build 輸出至不同計(jì)算機(jī)當(dāng)中。
除此之外,您還需要單獨(dú)發(fā)布 linking 以及 razor page publishing 等操作。
2
.NET Core 工具:本地安裝
.NET Core 工具也經(jīng)過(guò)更新以支持本地安裝。這些工具比 .NET Core 2.1 版本中的原有全局工具更強(qiáng)大。
本地安裝具有以下特性:
限制工具的使用范圍。
始終使用該工具的某一特定版本,該版本可能不同于全局安裝工具或者其它本地安裝工具。具體基于本地工具 manifest 文件中定義的版本。
可使用 dotnet 命令啟動(dòng),例如 dotnet mytool。
備注:請(qǐng)參閱本地工具早期預(yù)覽版說(shuō)明文檔以了解更多細(xì)節(jié)信息。
.NET Core SDK 安裝程序現(xiàn)在將就地升級(jí)
Windows 版本的 .NET Core SDK MSI 安裝程序?qū)⒂瓉?lái)就地升級(jí)。這將減少開(kāi)發(fā)者計(jì)算機(jī)及生產(chǎn)計(jì)算機(jī)上所需安裝的 SDK 數(shù)量。
此項(xiàng)升級(jí)策略將專門針對(duì) .NET Core SDK 功能范圍。各功能范圍在版本號(hào)中以最后三位數(shù)字中的百位體現(xiàn),例如 3.0.101 與 3.0.201 代表兩個(gè)不同的版本功能范圍,而 3.0.101 與 3.0.199 則處于同一版本功能范圍。
這意味著當(dāng) .NET Core SDK 3.0.101 正式發(fā)布并安裝完畢后,.NET Core SDK 3.0.100 將被從計(jì)算機(jī)中刪除(如果存在)。當(dāng) .NET Core SDK 3.0.200 可用并安裝在同一臺(tái)計(jì)算機(jī)上時(shí),.NET Core SDK 3.0.101 則不會(huì)被刪除。在這種情況下,系統(tǒng)仍將默認(rèn)使用 .NET Core SDK 3.0.200,但如果將其配置為通過(guò) global.json 起效,則系統(tǒng)仍然使用 .NET Core SDK 3.0.101(或者更高版本的.1xx 版本)。
這種方法與 global.json 的行為保持一致,允許在各補(bǔ)丁版本之間進(jìn)行前滾 ,但無(wú)法跨越 SDK 功能范圍。因此,通過(guò) SDK 安裝程序并進(jìn)行升級(jí),可確保應(yīng)用程序不會(huì)因缺少 SDK 而發(fā)生錯(cuò)誤。對(duì)于已經(jīng)安裝了 Visual Studio 必要 SDK 的用戶,其功能范圍也將與 Visual Studio 安裝情況保持一致。
若需了解更多細(xì)節(jié)信息,請(qǐng)參閱:
.NET Core 版本控制
刪除.NET Core SDK 版本
.NET Core SDK 體積改進(jìn)
在 .NET Core 3.0 當(dāng)中,.NET Core SDK 的體積明顯更小。主要原因在于,我們轉(zhuǎn)而采用出于各種目的(引用 assembiles、框架、模板等)的專用“內(nèi)置包”,從而改變了我們構(gòu)建 SDK 的方式。在以往的版本(包括 .NET Core 2.2)當(dāng)中,我們一直利用 NuGet 軟件包構(gòu)建 SDK,但其中包含大量并不需要的構(gòu)件,且對(duì)存儲(chǔ)空間造成嚴(yán)重浪費(fèi)。
.NET Core 3.0 SDK 體積(括號(hào)中為體積變量)
Linux 與 MacOS 版本的體積變化最為顯著,相比之下 Windows 版本的改進(jìn)較小,這是因?yàn)槲覀冊(cè)?.NET Core 3.0 當(dāng)中添加了 WPF 與 Windows Forms。令人驚訝的是,盡管新增了 WPF 與 Windows Forms,安裝程序的體積仍然比原先小了一點(diǎn)。
大家也可以在 .NET Core SDK Docker 鏡像當(dāng)中感受到這一瘦身效果(僅限于 x64 Debian 與 Alpine)。
大家可以在 .NET Core 3.0 SDK 體積改進(jìn)文檔中了解我們?nèi)绾斡?jì)算這些文件的大小。這里提供詳細(xì)的說(shuō)明,您可以遵循同樣的方法在自己的環(huán)境中運(yùn)行測(cè)試。
Docker 發(fā)布更新
微軟各團(tuán)隊(duì)目前都在面向微軟容器注冊(cè)表(MCR)發(fā)布新的容器鏡像。這一變化主要有兩大原因:
將微軟提供的容器鏡像協(xié)同至多個(gè)注冊(cè)表,包括 Docker Hub 與 Red Hat。
利用微軟 Azure 作為全球 CDN 以交付微軟提供的容器鏡像。
在.NET 團(tuán)隊(duì),我們目前將所有 .NET Core 鏡像發(fā)布至 MCR。我們?cè)?Docker Hub 上維護(hù)有自己的主頁(yè),并打算長(zhǎng)期保持運(yùn)營(yíng)。在另一方面,MCR 并不提供類似的頁(yè)面,但可以通過(guò) Docker Hub 等公共注冊(cè)表為用戶提供與鏡像有關(guān)的信息。Microsoft.dotnet 以及 microsoft.dotnet-nightly 等舊有代碼庫(kù)鏈接現(xiàn)在都已經(jīng)指向新的地址。不過(guò)舊有位置中的各鏡像仍將存在,不會(huì)被刪除。
在支持生命周期之內(nèi),我們將繼續(xù)為 .NET Core 各個(gè)版本的代碼庫(kù)提供浮動(dòng)標(biāo)記服務(wù)。例如,2.1-sdk、2.2-runtime 以及 lastest 就屬于此類浮動(dòng)標(biāo)記。像 2.1.2-sdk 這類包含三個(gè)數(shù)字的標(biāo)簽將不再提供,我們已經(jīng)在版本號(hào)內(nèi)加以體現(xiàn)。接下來(lái),我們將僅通過(guò) MCR 支持 .NET Core 3.0 鏡像。
例如,現(xiàn)在用于提取 3.0 SDK 鏡像的正確標(biāo)簽字符串應(yīng)該為:
新的 MCR 字符串將由 docker pull 以及 Dockerfile FROM 語(yǔ)句共同使用。
感興趣的朋友可以參閱微軟容器注冊(cè)表中的現(xiàn)有 .NET Core 鏡像以了解更多細(xì)節(jié)信息。
SDK Docker 鏡像中包含 PowerShell Core
應(yīng)社區(qū)的要求,PowerShell Core 已經(jīng)被添加至 .NET Core SDK Docker 容器鏡像當(dāng)中。PowerShell Core 是一套跨平臺(tái)(Windows、Linux 以及 MacOS)自動(dòng)化與配置工具 / 框架,能夠與大家的現(xiàn)有工具良好協(xié)作,并針對(duì)結(jié)構(gòu)化數(shù)據(jù)(例如 JSON)CSV、XML 等)、REST API 以及對(duì)象模型進(jìn)行了優(yōu)化。其中包含一個(gè)命令行 shell、一種相關(guān)腳本語(yǔ)言以及一套用于處理 cmdlets 的框架。
現(xiàn)在,大家可以通過(guò)以下 Docker 命令將 PowerShell Core 視為 .NET Core SDK 容器鏡像中的一部分:
目前只有兩種將 PowerShell 引入 .NET Core SDK 容器鏡像的方法,具體如下:
面向任意操作系統(tǒng)利用 PowerShell 語(yǔ)法編寫 .NET Core 應(yīng)用程序 Dockerfiles。
編寫能夠輕松實(shí)現(xiàn)容器化的 .NET Core 應(yīng)用程序 / 庫(kù)構(gòu)建邏輯。
以下為容器化 build(存儲(chǔ)卷掛載)的 PowerShell 啟動(dòng)語(yǔ)法示例:
為了讓第二條示例命令正常起效,我們需要在 Linux 上確保.ps1 文件具有以下格式,并需要利用 Unix(LF)而非 Windows(CRLF)作為行尾以執(zhí)行格式化:
備注:PowerShell Core 目前已經(jīng)作為.NET Core 3.0 SDK 容器鏡像的一部分進(jìn)行發(fā)布,而不再歸屬于 .NET Core 3.0 SDK。
紅帽軟件支持
2015 年 4 月,我們宣布 .NET Core 將全面登陸 Red Hat Enterprise Linux。通過(guò)與紅帽方面的出色工程合作,.NET Core 1.0 于 2016 年 6 月以組件的形式出現(xiàn)在紅帽系列軟件當(dāng)中。另外,在與紅帽工程師們的持續(xù)交流當(dāng)中,我們也了解到 Linux 社區(qū)在軟件發(fā)布方面的反饋與意見(jiàn)。
過(guò)去四年以來(lái),紅帽公司先后發(fā)布了多次面向 .NET Core 的更新與大版本升級(jí),包括 2.1 與 2.2 版本。在 .NET Core 2.2 版本當(dāng)中,紅帽公司將其 .NET Core 產(chǎn)品擴(kuò)展至包括 OpenShift 在內(nèi)的多個(gè)平臺(tái)。而隨著 RHEL 8 的發(fā)布,我們也高興地看到微軟 .NET Core 2.1 以及即將推出的 3.0 版本都被納入紅帽 Application Streams 當(dāng)中。
3
總結(jié)
.NET Core 3.0 是 .NET Core 發(fā)展歷程中的又一重要新版本,其中帶來(lái)了大量改進(jìn)。我們建議大家盡快著手采用新的 .NET Core 3.0。新版本通過(guò)多種方式對(duì) .NET Core 做出巨大改進(jìn),例如顯著降低了 SDK 的體積、極大提升對(duì)于關(guān)鍵場(chǎng)景(例如容器以及 Windows 桌面應(yīng)用程序)的支持效果。受到篇幅所限,這里無(wú)法一一列出其它小的改進(jìn),但相信隨著時(shí)間的推移,大家一定能夠從這些細(xì)節(jié)增強(qiáng)中受益。
最后,希望大家能夠在接下來(lái)的使用當(dāng)中與我們分享體驗(yàn)與感受。希望開(kāi)發(fā)者喜歡 .NET Core 3.0,我們也熱切希望根據(jù)大家的喜好對(duì)產(chǎn)品進(jìn)行打磨。
https://devblogs.microsoft.com/dotnet/announcing-net-core-3-0/
責(zé)任編輯:中山網(wǎng)站建設(shè)
【網(wǎng)訊網(wǎng)絡(luò)】國(guó)家高新技術(shù)企業(yè)》十年專注軟件開(kāi)發(fā),網(wǎng)站建設(shè),網(wǎng)頁(yè)設(shè)計(jì),APP開(kāi)發(fā),小程序,微信公眾號(hào)開(kāi)發(fā),定制各類企業(yè)管理軟件(OA、CRM、ERP、訂單管理系統(tǒng)、進(jìn)銷存管理軟件等)!服務(wù)熱線:0760-88610046、13924923903,http://www.wansion.net
*請(qǐng)認(rèn)真填寫需求,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。