深度探秘.NET 5.0
2020 中國(guó).NET 開(kāi)發(fā)者峰會(huì)正式啟動(dòng)?,歡迎大家提交演講主題或者購(gòu)買(mǎi)超級(jí)早鳥(niǎo)票。
今年11月10號(hào) .NET 5.0 如約而至。這是.NET All in one后的第一個(gè)版本,雖然不是LTS(Long term support)版本,但是是生產(chǎn)環(huán)境可用的。
微軟從.NET 5 Preview 1就開(kāi)始在自己的網(wǎng)站上使用 .NET 5, (Bing.com、dot.net已升級(jí)并運(yùn)行了數(shù)個(gè)月),同時(shí)早期的.NET Core版本可以直接升級(jí)到.NET 5. ?有著微軟得背書(shū),所以大家是可以放心使用的。
接下來(lái),我們深入了解一下.NET 5.0這次帶來(lái)了哪些新的特性。
一
.NET 5.0 的一些亮點(diǎn)(Highlights)
1.?通過(guò)線上(生產(chǎn)環(huán)境)測(cè)試(battle-tested)?:?.NET5.0 通過(guò)在Bing.com和dot.net 托管運(yùn)行數(shù)個(gè)月,全面通過(guò)了線上驗(yàn)證,這證明這個(gè)版本是生產(chǎn)可用的
2. 性能大幅提升:GC、JIT、正則表達(dá)式、多線程和異步處理、集合、LINQ、網(wǎng)絡(luò)訪問(wèn)、JSON序列化、gRPC等等,了解詳細(xì)可以訪問(wèn)
Performance Improvements in .NET 5.0
Arm64 Performance in .NET 5.0
gRPC.
3. C# 9和F# 9 的語(yǔ)言提升:例如C#9的頂級(jí)程序和記錄record,F#5提供了交互式編程,并提高了.NET的性能。
4. .NET庫(kù)增強(qiáng)了Json序列化,正則表達(dá)式和HTTP(HTTP 1.1,HTTP / 2)的性能。這一點(diǎn)在第二條中已經(jīng)有所涉及。
5.?P95 的延遲有所減少,得益于GC、分層編譯和其他組件的一些改進(jìn)
6.更好、更靈活的應(yīng)用部署選項(xiàng):ClickOnce客戶端應(yīng)用程序發(fā)布,單文件應(yīng)用程序,減小的容器映像大小以及添加的Server Core容器映像。
7.平臺(tái)支持的范圍進(jìn)一步擴(kuò)展:Windows Arm64和WebAssembly
文中藍(lán)色標(biāo)注文檔鏈接如下:
Performance Improvements in .NET 5.0
https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-5/?https://devblogs.microsoft.com/dotnet/introducing-net-5?WT.mc_id=DT-MVP-5003918
Arm64 Performance in .NET 5.0
https://devblogs.microsoft.com/dotnet/Arm64-performance-in-net-5/?https://devblogs.microsoft.com/dotnet/introducing-net-5?WT.mc_id=DT-MVP-5003918
gRPC.
https://devblogs.microsoft.com/aspnet/grpc-performance-improvements-in-net-5?WT.mc_id=DT-MVP-5003918
Windows Arm64
https://github.com/dotnet/runtime/issues/36699
WebAssembly
https://github.com/dotnet/runtime/issues/38367
二
再看統(tǒng)一平臺(tái)的愿景
2019年5月6號(hào),微軟發(fā)布了.NET 5.0 統(tǒng)一平臺(tái)的愿景:將來(lái)只會(huì)有一個(gè).NET,您將可以使用它來(lái)定位Windows,Linux,macOS,iOS,Android,tvOS,watchOS和WebAssembly等。
實(shí)現(xiàn)這一愿景的第一步是整合.NET倉(cāng)庫(kù),即:整合關(guān)鍵的.NET代碼庫(kù), 這是為.NET運(yùn)行庫(kù)和庫(kù)提供一個(gè)存儲(chǔ)庫(kù)是在各處交付相同產(chǎn)品的前提。Blazor就是代碼合并和.NET統(tǒng)一的最佳示例:Blazor WebAssembly的運(yùn)行時(shí)和庫(kù)現(xiàn)在是從合并的dotnet /運(yùn)行時(shí)倉(cāng)庫(kù)中構(gòu)建的。這意味著服務(wù)器上的Blazor WebAssembly和Blazor使用與完全相同的代碼List<T>。
代碼整合后,.NET Framework怎么辦?
.NET Framework仍然是受支持的Microsoft產(chǎn)品,并且每個(gè)新版本的Windows都將繼續(xù)支持.NET Framework。去年,微軟宣布已停止向.NET Framework添加新功能,逐步向.NET Core添加更多的.NET Framework API。
這就意味著,.NET Framework已經(jīng)停更了,版本目前停留在.NET Framework 4.8.?這也是沒(méi)辦法的事情,統(tǒng)一后的.NET, 從.NET5.0開(kāi)始迭代了。這次.NET 5.0的Release列表也能發(fā)現(xiàn)這個(gè)情況:
在上述情況下,目前是將.NET Framework升級(jí)到.NET Core的最佳時(shí)機(jī)了。如果比較在意LTS版本,也可以等到明年.NET 6統(tǒng)一升級(jí)。對(duì)于此,微軟的建議是:
對(duì)于.NET Framework客戶端開(kāi)發(fā)人員,.NET 5.0支持Windows窗體和WPF。
?對(duì)于.NET Framework服務(wù)器開(kāi)發(fā)人員, 如果采用ASP.NET Core才能使用.NET 5.0。
對(duì)于Web Forms開(kāi)發(fā)人員,Blazor通過(guò)高效且更加現(xiàn)代的實(shí)現(xiàn)方式提供類(lèi)似的開(kāi)發(fā)人員體驗(yàn)。
對(duì)于WCF服務(wù)器和Workflow用戶可以查看支持這些框架的社區(qū)項(xiàng)目。
以上,對(duì)于統(tǒng)一后的.NET 5.0, 廣大.NET Developers 可以放心、開(kāi)心地去擁抱這次升級(jí)和統(tǒng)一,這代表了.NET的未來(lái)。
文中藍(lán)色標(biāo)注文檔鏈接如下:
.NET 5.0 統(tǒng)一平臺(tái)的愿景
https://devblogs.microsoft.com/dotnet/introducing-net-5?WT.mc_id=DT-MVP-5003918
支持這些框架的社區(qū)項(xiàng)目
https://devblogs.microsoft.com/dotnet/supporting-the-community-with-wf-and-wcf-oss-projects/
三
深入了解一下編程語(yǔ)言層面的提升(C# 9 和 F# 5)
C#9和F#5是.NET 5.0版本的一部分,被包含在.NET 5.0 SDK中。接下來(lái)詳細(xì)看一下C# 9 的一些語(yǔ)言新特性(F# 5用的比較少,不再做詳細(xì)介紹):
1.?Top-level programs 頂級(jí)程序
大家會(huì)問(wèn)這是什么?這是在頂級(jí)編寫(xiě)程序的一種更簡(jiǎn)單的方式:一個(gè)更簡(jiǎn)單的 Program.cs 文件。
我們知道,原先在Program類(lèi)中,必須有Main函數(shù),這是程序的一個(gè)EntryPoint入口。
using System;namespace NET5Demo {class Program{static void Main(string[] args){Console.WriteLine("Hello World!");}} }?.NET 5引入Top-level programs 后,我們不需要寫(xiě)Main函數(shù)了。可以直接這么寫(xiě):
System.Console.WriteLine("Hello World!");大家會(huì)有疑問(wèn),真的沒(méi)有Main函數(shù)了嗎?其實(shí)這是個(gè)語(yǔ)法糖,我們通過(guò)IL Spy看一下反編譯后的代碼:
2. 邏輯模式和屬性模式匹配(Logical and property patterns)
我們可以使用not or and 實(shí)現(xiàn)更強(qiáng)的更靈活的邏輯模式匹配:
先看一個(gè)邏輯匹配的Demo:
var input = Console.ReadKey(); if (input.KeyChar is 'Y' or 'y') {Console.WriteLine("You choosed yes!"); }再看一個(gè)Switch的Demo:?
int score = 90; switch (score) {case 0:Console.WriteLine("0分.");break;case > 0 and <= 60:Console.WriteLine("合格.");break;case > 60 and <= 80:Console.WriteLine("優(yōu)秀.");break;case > 80 and <= 100:Console.WriteLine("卓越.");break; }屬性模式匹配:通過(guò)兩個(gè){},實(shí)現(xiàn)對(duì)對(duì)象屬性的模式匹配。
Type type = Type.GetType("System.String"); if (type is not null and { FullName: "System.String" }) {Console.WriteLine("It's type is System.String."); }3. record類(lèi)型
record是一個(gè)新增的引用類(lèi)型,與class很像,那么大家會(huì)問(wèn)?為什么增加一個(gè)record類(lèi)型呢?它的使用場(chǎng)景是什么呢?
答案:為了方便比較數(shù)據(jù)是否一致。
我們寫(xiě)個(gè)代碼示意一下:
假設(shè)我們有個(gè)User類(lèi),包含ID、Name、Gender、Tel幾個(gè)屬性,如果我們要對(duì)比2個(gè)User對(duì)象是否相等,我們可能需要逐個(gè)屬性對(duì)比,或重寫(xiě)Equals、GetHashCode方法。
那么如果我們用record類(lèi)型呢?
record User(int Id, string Name, int Gender, string Tel);做個(gè)對(duì)象對(duì)比的Demo:
var userA = new User(1, "小米", 1, "123456789"); var userB = new User(1, "小米", 1, "123456789"); if (userA == userB) {Console.WriteLine("這是一個(gè)用戶."); }總結(jié)一下:record類(lèi)型讓開(kāi)發(fā)省去了重寫(xiě)相等比較的業(yè)務(wù)邏輯,同時(shí)簡(jiǎn)化了類(lèi)型定義和初始化。
4. 可空注解的增加和改進(jìn)
目前.NET library 類(lèi)庫(kù),已經(jīng)全面設(shè)置了是否可空注解。其實(shí)這個(gè)特性其實(shí)在C# 8.0已經(jīng)引入:C#8.0 引入了“可為空引用類(lèi)型”和“不可為空引用類(lèi)型”,使你能夠?qū)σ妙?lèi)型變量的屬性作出重要聲明?:
? #nullable enable
? class A{ }
即.NET 5.0的類(lèi)庫(kù)中已經(jīng)全面更新了這個(gè)注解,方便開(kāi)發(fā)時(shí)進(jìn)行查看。
同時(shí),這次引入新的成員是否為空的注解:
MemberNotNull 和 MemberNotNullWhen,例如以下的代碼:
class UserManager {User user = new User(1, "小米", 1, "123456789");[MemberNotNull(nameof(user))]public string GetUserName(string id){return user.Name;} }編譯器會(huì)智能提示:CS8602警告
文中藍(lán)色標(biāo)注文檔鏈接如下:
C#8.0 引入了“可為空引用類(lèi)型”和“不可為空引用類(lèi)型”,使你能夠?qū)σ妙?lèi)型變量的屬性作出重要聲明
https://docs.microsoft.com/zh-cn/dotnet/csharp/nullable-references
四
工具類(lèi)的新變化
.NET 5.0 改進(jìn)了Windows窗體設(shè)計(jì)器,更改了目標(biāo)框架適用于.NET 5.0及更高版本的方式,更改了WinRT的支持方式,以及其他的一些改進(jìn)。
1. Windows窗體設(shè)計(jì)器:winform設(shè)計(jì)器
Windows Forms設(shè)計(jì)器(用于.NET Core 3.1和.NET 5.0)已經(jīng)在Visual Studio 16.8中進(jìn)行了更新,現(xiàn)在支持所有Windows Forms控件。它還支持WinForms控件的Telerik UI。設(shè)計(jì)器包括您期望的所有設(shè)計(jì)器功能,包括:拖放,選擇,移動(dòng)和調(diào)整大小,剪切/復(fù)制/粘貼/刪除控件,與屬性窗口集成,事件生成等。數(shù)據(jù)綁定和對(duì)更廣泛的第三方控件的支持即將推出。
2.?.NET 5.0目標(biāo)框架
新增一個(gè)Console類(lèi)型工程后,選擇目標(biāo)框架是.NET 5.0, 其Project文件內(nèi)容是這樣的:
<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><OutputType>Exe</OutputType><TargetFramework>net5.0</TargetFramework></PropertyGroup> </Project>新增一個(gè)Windows窗體應(yīng)用工程后,選擇目標(biāo)框架是.NET 5.0, 其Project文件內(nèi)容是這樣的:
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop"><PropertyGroup><OutputType>WinExe</OutputType><TargetFramework>net5.0-windows</TargetFramework><UseWindowsForms>true</UseWindowsForms></PropertyGroup> </Project>Windows桌面API(包括Windows窗體,WPF和WinRT)僅在定位時(shí)可用net5.0-windows。同時(shí)也可以指定操作系統(tǒng)版本,例如net5.0-windows7或net5.0-windows10.0.17763.0(對(duì)于Windows October 2018 Update)。
如果要使用WinRT API,則需要定位Windows 10版本。
總結(jié)一下:
net5.0 是.NET 5.0的新目標(biāo)框架綽號(hào),Target Framework Moniker(TFM)。
net5.0結(jié)合并替換netcoreapp和netstandard TFM。
net5.0支持.NET Framework兼容模式
net5.0-windows 將用于公開(kāi)Windows特定功能,包括Windows窗體,WPF和WinRT API。
.NET 6.0將使用相同的方法,并帶有net6.0和將添加net6.0-ios和net6.0-android。
特定于操作系統(tǒng)的TFM可以包含操作系統(tǒng)版本號(hào),例如net6.0-ios14。
可移植的API(如ASP.NET Core)可與一起使用net5.0。帶有的Xamarin形式也是如此net6.0。
3.?WinRT Interop的重大改進(jìn)
在以Windows API為目標(biāo)這一主題上,微軟已經(jīng)移至一個(gè)新模型,以作為.NET 5.0的一部分來(lái)支持WinRT API。這包括調(diào)用API(在任一方向上;CLR <==> WinRT),兩個(gè)類(lèi)型系統(tǒng)之間的數(shù)據(jù)封送處理以及打算在類(lèi)型系統(tǒng)或ABI邊界上統(tǒng)一對(duì)待的類(lèi)型的統(tǒng)一(即“投影類(lèi)型” ”,IEnumerable<T>并且IIterable<T>是示例)。
從.NET 5.0開(kāi)始,原有的WinRT互操作體系已被移除。這是一個(gè)巨大的變化。這意味著使用WinRT和.NET Core 3.x的應(yīng)用程序和庫(kù)需要重新開(kāi)發(fā)對(duì)接,并且不能按原樣在.NET 5.0上運(yùn)行。
使用WinRT API的庫(kù)將需要多目標(biāo)來(lái)管理.NET Core 3.1和.NET 5.0之間的這種差異。
未來(lái),.NET 將依靠Windows中的WinRT團(tuán)隊(duì)提供的新CsWinRT工具。它生成基于C#的WinRT互操作程序集,可以通過(guò)NuGet交付該程序集。Windows團(tuán)隊(duì)正是針對(duì)Windows中的WinRT API所做的。希望將WinRT(在Windows上)用作互操作系統(tǒng)的任何人都可以使用該工具,以將本機(jī)API公開(kāi)給.NET或?qū)?NET API公開(kāi)給本機(jī)代碼。
關(guān)于CsWinRT工具,已經(jīng)發(fā)布了1.0版本,具體可以參考鏈接:https://blogs.windows.com/windowsdeveloper/2020/11/10/announcing-c-winrt-version-1-0-with-the-net-5-ga-release/
4. .NET Native Export/ .NET 本地導(dǎo)出
即本機(jī)二進(jìn)制文件啟用導(dǎo)出功能。
.NET 開(kāi)發(fā)團(tuán)隊(duì)的Aaron Robinson一直在從事.NET Native Exports項(xiàng)目,該項(xiàng)目為將.NET組件作為本機(jī)庫(kù)發(fā)布提供了更完整的體驗(yàn)。
.NET Native導(dǎo)出項(xiàng)目能夠?qū)崿F(xiàn):
公開(kāi)自定義的本地出口。
不需要像COM這樣的高級(jí)互操作技術(shù)。
跨平臺(tái)工作
類(lèi)似的實(shí)現(xiàn)技術(shù),還有:
Unmanaged Exports
DllExport
5. 事件管道
事件管道是在.NET Core 2.2中添加的新子系統(tǒng)和API,可以在任何操作系統(tǒng)上執(zhí)行性能和其他診斷調(diào)查。
在.NET 5.0中,事件管道已得到擴(kuò)展,以使事件探查器能夠?qū)懭胧录艿朗录?/p>
對(duì)于以前依靠ETW(在Windows上)監(jiān)視應(yīng)用程序行為和性能的分析探查器,來(lái)說(shuō)是一個(gè)很好的方案和選擇。
這里不做詳細(xì)展開(kāi)了。
6. 轉(zhuǎn)儲(chǔ)調(diào)試,Dump分析調(diào)試
調(diào)試托管代碼需要了解托管對(duì)象和構(gòu)造。數(shù)據(jù)訪問(wèn)組件(DAC)是運(yùn)行時(shí)執(zhí)行引擎的子集,該引擎具有這些構(gòu)造的知識(shí),并且可以在沒(méi)有運(yùn)行時(shí)的情況下訪問(wèn)這些托管對(duì)象。
現(xiàn)在,可以使用WinDBG或Windows在Windows上分析在Linux上收集的.NET Core進(jìn)程轉(zhuǎn)儲(chǔ)dotnet dump analyze。
本次發(fā)布還增加了對(duì)從macOS上運(yùn)行的.NET進(jìn)程捕獲ELF轉(zhuǎn)儲(chǔ)的支持。由于ELF不是lldbmacOS上的本機(jī)可執(zhí)行文件(像這樣的本地調(diào)試器將無(wú)法與這些轉(zhuǎn)儲(chǔ)一起使用)文件格式,因此我們將其設(shè)為啟用功能。
要在macOS上支持轉(zhuǎn)儲(chǔ)收集,請(qǐng)?jiān)O(shè)置環(huán)境變量COMPlus_DbgEnableElfDumpOnMacOS=1。可以使用來(lái)分析產(chǎn)生的轉(zhuǎn)儲(chǔ)dotnet dump analyze。
7. 打印環(huán)境信息
隨著.NET擴(kuò)展了對(duì)新操作系統(tǒng)和芯片體系結(jié)構(gòu)的支持,有時(shí)需要一種打印環(huán)境信息的方法。.NET 5.0 創(chuàng)建了一個(gè)簡(jiǎn)單的.NET工具來(lái)執(zhí)行此操作,稱(chēng)為dotnet-runtimeinfo。可以使用以下命令安裝和運(yùn)行該工具:
dotnet tool install -g dotnet-runtimeinfo dotnet-runtimeinfo五
運(yùn)行時(shí)和類(lèi)庫(kù)的提升
1.?RyuJIT的代碼質(zhì)量提升
可以參考這個(gè)鏈接:Performance Improvements in RyuJIT in .NET Core and .NET Framework
2. GC垃圾回收
Card mark stealing – dotnet/coreclr #25986?–?Server GC (on different threads) can now work-steal while marking gen0/1 objects held live by older generation objects. This means that ephemeral GC pauses are shorter for scenarios where some GC threads took much longer to mark than others.? ServerGC 中標(biāo)記階段的耗時(shí)更短了
Introducing Pinned Object Heap – dotnet/runtime #32283?— Adds the Pinned Object Heap (POH). This new heap (a peer to the Large Object Heap (LOH)) will allow the GC to manage pinned objects separately, and as a result avoid the negative effects of pinned objects on the generational heaps. 新增固定對(duì)象堆(POH)。此新堆(與大對(duì)象堆(LOH)對(duì)等)將允許GC單獨(dú)管理固定對(duì)象,從而避免固定對(duì)象對(duì)堆的負(fù)面影響。
Allow allocating large object from free list while background sweeping SOH?— Enabled LOH allocations using the free list while BGC is sweeping SOH. Previously this was only using end of segment space on LOH. This allowed for better heap usage.允許在后臺(tái)掃描SOH時(shí)從空閑列表中分配大對(duì)象
Background GC suspension fixes – dotnet/coreclr #27729?— Suspension fixes to reduce time for both BGC and user threads to be suspended. This reduces the total time it takes to suspend managed threads before a GC can happen. dotnet/coreclr #27578 also contributes to the same outcome. 掛起修復(fù)程序可減少BGC和用戶線程掛起的時(shí)間。這樣可以減少發(fā)生GC之前掛起托管線程所需的總時(shí)間。
Fix named cgroup handling in docker?— Added support to read limits from named cgroups. Previously we only read from the global one.?修復(fù)了docker中命名cgroup處理的問(wèn)題—添加了對(duì)從命名cgroups讀取限制的支持
Optimize vectorized sorting – dotnet/runtime #37159?— vectorized mark list sorting in GC which reduces the ephemeral GC pause time (also?dotnet/runtime #40613).?GC中的矢量化標(biāo)記列表排序,減少了短暫的GC暫停時(shí)間
Generational aware analysis – dotnet/runtime #40322?— generational aware analysis that allows you to determine what old generation objects hold on to younger generation objects thus making them survive and contribute to ephemeral GC pause time.GC代感知分析,能夠確定哪些舊世代對(duì)象保留在年輕代對(duì)象上,從而使它們得以生存并有助于短暫的GC暫停時(shí)間。
Optimize decommitting GC heap memory pages – dotnet/runtime #35896?— optimized decommit, much better decommit logic and for Server GC took decommit completely out of the “stop the world” phase which reduced blocking GC pause time.優(yōu)化了取消授權(quán),更好的取消授權(quán)邏輯,對(duì)于Server GC,完全取消了“停止一切”階段的授權(quán),從而減少了阻塞GC的暫停時(shí)間
整體總結(jié)一下,Server GC延遲更低了,CPU消耗更少、性能更好了。
3. Windows Arm64的支持
.NET應(yīng)用程序現(xiàn)在可以在Windows Arm64上本機(jī)運(yùn)行。在.NET Core 3.0中添加的對(duì)Linux Arm64的支持(對(duì)glibc和musl的支持)。使用.NET 5.0,可以在Windows Arm64設(shè)備(例如Surface Pro X)上開(kāi)發(fā)和運(yùn)行應(yīng)用程序。也可以通過(guò)x86仿真在Windows Arm64上運(yùn)行.NET Core和.NET Framework應(yīng)用程序。但是本機(jī)運(yùn)行Arm64具有更好的性能。
同時(shí),.NET 5.0 SDK當(dāng)前在Windows Arm64上不包含Windows桌面組件-Windows窗體和WPF。Windows Arm64上支持SDK,控制臺(tái)和ASP.NET Core應(yīng)用程序,但Windows桌面組件不支持。
4. Arm64性能優(yōu)化
.NET 5.0 中主要針對(duì)Arm64平臺(tái)做了以下優(yōu)化:
調(diào)整Arm64的JIT優(yōu)化(示例1)
啟用并利用Arm64硬件內(nèi)部函數(shù)(示例2)。
調(diào)整Arm64庫(kù)中對(duì)性能至關(guān)重要的算法(示例3)。
更多詳細(xì)信息,請(qǐng)參見(jiàn)在.NET 5.0中提高Arm64性能。
5.?P95 +延遲改進(jìn)
Stack Overflow的一位工程師Nick Craver最近分享了他們升級(jí).NET Core后,對(duì)延遲的改進(jìn):
問(wèn)題頁(yè)面的展現(xiàn)時(shí)間中值從大約21毫秒(由于GC而有所增加)降至約15毫秒。
第95個(gè)百分位數(shù)從?40ms下降到?30ms(相同測(cè)量)。第99位從?60ms降至?45ms。
.NET項(xiàng)目組的解讀是這樣的:固定對(duì)象一直是GC性能的長(zhǎng)期挑戰(zhàn),因?yàn)樗鼈儠?huì)加速(或?qū)е?#xff09;內(nèi)存碎片。.NET 5.0為固定對(duì)象添加了新的GC堆。該固定對(duì)象堆是基于這樣的假設(shè)(以空間換時(shí)間),他們的存在會(huì)導(dǎo)致不相稱(chēng)的性能挑戰(zhàn)極少數(shù)固定的對(duì)象。將固定的對(duì)象(尤其是由.NET庫(kù)作為實(shí)現(xiàn)細(xì)節(jié)創(chuàng)建的對(duì)象)移動(dòng)到唯一的區(qū)域是有意義的,而垃圾回收代的GC堆幾乎沒(méi)有或沒(méi)有固定的對(duì)象,因此具有更高的性能。
6. 分層編譯性能改進(jìn)
關(guān)于分層編譯,大家可以參考這個(gè)連接:https://devblogs.microsoft.com/dotnet/tiered-compilation-preview-in-net-core-2-1
在.NET 5.0中對(duì)分層編譯進(jìn)行了兩項(xiàng)重大改進(jìn)。下面這2段有點(diǎn)復(fù)雜,也比較晦澀
分層編譯的主要機(jī)制是調(diào)用計(jì)數(shù)。一旦某個(gè)方法被調(diào)用了n次,運(yùn)行時(shí)就會(huì)要求JIT以更高的質(zhì)量重新編譯該方法。從最早的性能分析中,發(fā)現(xiàn)采用計(jì)數(shù)機(jī)制太慢,但是沒(méi)有找到解決該問(wèn)題的直接方法。.NET 5.0中改進(jìn)了分層JIT編譯所使用的調(diào)用計(jì)數(shù)機(jī)制,以平滑啟動(dòng)期間的性能。在過(guò)去的發(fā)行版中,已經(jīng)發(fā)現(xiàn)在進(jìn)程生命周期的前10到15秒鐘內(nèi),性能會(huì)發(fā)生不可預(yù)測(cè)的變化(主要是針對(duì)Web服務(wù)器)。目前應(yīng)該已經(jīng)解決了。
另一個(gè)性能挑戰(zhàn)是對(duì)具有循環(huán)的方法使用分層編譯。根本的問(wèn)題是,您可以使用帶有循環(huán)多次的循環(huán)的冷方法(僅調(diào)用一次或幾次;$ lt; n)。我們稱(chēng)這種病理情況為“冷方法”。熱循環(huán)”。可以想象Main應(yīng)用程序的方法會(huì)發(fā)生這種情況。結(jié)果,默認(rèn)情況下,我們禁用了帶循環(huán)方法的分層編譯。相反,使應(yīng)用程序可以選擇使用帶循環(huán)的分層編譯。在某些情況下看到了個(gè)位數(shù)的高性能改進(jìn)后,PowerShell就是選擇執(zhí)行此操作的應(yīng)用程序。
為了更好地解決循環(huán)問(wèn)題,.NET 實(shí)現(xiàn)了棧上替換(OSR)。這類(lèi)似于Java虛擬機(jī)具有的同名功能。OSR允許在方法執(zhí)行過(guò)程中重新編譯當(dāng)前正在運(yùn)行的方法執(zhí)行的代碼,而這些方法是“堆棧上”活動(dòng)的。該功能目前處于試驗(yàn)和選擇啟用狀態(tài),并且僅在x64上可用。
要使用OSR,必須啟用多個(gè)功能。目前.NET 5.0中沒(méi)有啟用OSR,這個(gè)功能尚未決定在生產(chǎn)環(huán)境中是否啟用,所以這個(gè)技術(shù)點(diǎn),了解即可。
7. JSON序列化 System.Text.Json
.NET 5.0 對(duì)System.Text.Json進(jìn)行了顯著改進(jìn),以提高性能和可靠性,同時(shí)API盡可能地和Newtonsoft.Json類(lèi)似。它還包括對(duì)將JSON對(duì)象反序列化對(duì)record類(lèi)型的支持。
同時(shí)微軟提供了System.Text.Json替換Newtonsoft.Json的遷移指南。該指南詳細(xì)闡明了這兩個(gè)API之間的關(guān)系。
如何從 Newtonsoft.Json 遷移到 System.Text.Json
JsonSerializer.NET 5.0中的性能顯著提高。Stephen Toub在.NET 5中的性能改進(jìn)中介紹了一些JsonSerializer改進(jìn)。
文中藍(lán)色標(biāo)注文檔鏈接如下:
Performance Improvements in RyuJIT in .NET Core and .NET Framework
https://devblogs.microsoft.com/dotnet/performance-improvements-in-ryujit-in-net-core-and-net-framework?WT.mc_id=DT-MVP-5003918
Card mark stealing – dotnet/coreclr #25986
https://github.com/dotnet/coreclr/pull/25986
Introducing Pinned Object Heap – dotnet/runtime #32283
https://github.com/dotnet/runtime/pull/32283
Allow allocating large object from free list while background sweeping SOH
https://github.com/dotnet/runtime/pull/2103
Background GC suspension fixes – dotnet/coreclr #27729
https://github.com/dotnet/coreclr/pull/27729
Fix named cgroup handling in docker
https://github.com/dotnet/runtime/pull/980
Optimize vectorized sorting – dotnet/runtime #37159
https://github.com/dotnet/runtime/pull/37159
Generational aware analysis – dotnet/runtime #40322
https://github.com/dotnet/runtime/pull/40332
dotnet/runtime #40613
https://github.com/dotnet/runtime/pull/40613
Optimize decommitting GC heap memory pages – dotnet/runtime #35896
https://github.com/dotnet/runtime/pull/35896
示例1
https://github.com/dotnet/runtime/pull/35675
示例2
https://github.com/dotnet/runtime/pull/34486
示例3
https://github.com/dotnet/runtime/issues/34198
在.NET 5.0中提高Arm64性能
https://github.com/dotnet/runtime/issues/35853
如何從 Newtonsoft.Json 遷移到 System.Text.Json
https://docs.microsoft.com/zh-cn/dotnet/standard/serialization/system-text-json-migrate-from-newtonsoft-how-to?pivots=dotnet-5-0&WT.mc_id=DT-MVP-5003918
JsonSerializer改進(jìn)
https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-5/#json?WT.mc_id=DT-MVP-5003918
六
應(yīng)用程序部署
應(yīng)用程序開(kāi)發(fā)完成后,根據(jù)實(shí)際的需要,可能會(huì)部署到Web服務(wù)器,云服務(wù)或客戶端計(jì)算機(jī),或者使用Azure DevOps或GitHub Actions之類(lèi)的服務(wù)進(jìn)行CI/CD。
.NET 5.0專(zhuān)注于改善單個(gè)文件應(yīng)用程序,減小docker多階段構(gòu)建的容器大小,并為使用.NET Core部署ClickOnce應(yīng)用程序提供更好的支持。
1. 容器
與容器的交互協(xié)作非常重要。這個(gè)版本中添加了OpenTelemetry支持,可以從應(yīng)用程序中捕獲分布式跟蹤和指標(biāo)。dotnet-monitor是一個(gè)新工具,可以作為從.NET進(jìn)程訪問(wèn)診斷信息的主要工具。特別是,我們已經(jīng)開(kāi)始構(gòu)建dotnet-monitor的容器變體,您可以將其用作應(yīng)用程序sidecar。同時(shí),.NET項(xiàng)目組正在構(gòu)建dotnet / tye,以提高微服務(wù)開(kāi)發(fā)人員在開(kāi)發(fā)和部署到Kubernetes環(huán)境中的效率。
.NET運(yùn)行時(shí)現(xiàn)在支持cgroup v2,這個(gè)API預(yù)計(jì)將在2020年以后成為與容器相關(guān)的重要API。Docker當(dāng)前使用cgroup v1(.NET已支持)。相比之下,cgroup v2比cgroup v1更簡(jiǎn)單,更有效且更安全。.NET 5.0將在cgroup v2環(huán)境中正常工作。
除了Nano Server,微軟還將發(fā)布Windows Server Core映像,努力減小Windows Server Core映像的大小。
更小的體積、更低的成本、更快的啟動(dòng)性能。.NET 5.0中將SDK映像重新建立在ASP.NET映像之上,而不是buildpack-deps,這樣可以顯著減小在多階段構(gòu)建方案中提取的聚合映像的大小。
2. 單文件應(yīng)用? ??
單個(gè)文件應(yīng)用程序作為單個(gè)文件發(fā)布和部署。該應(yīng)用程序及其依賴項(xiàng)都包含在該文件中。當(dāng)應(yīng)用程序運(yùn)行時(shí),依賴項(xiàng)直接從該文件加載到內(nèi)存中(不影響性能)。
在.NET 5.0中,單個(gè)文件應(yīng)用程序主要集中在Linux上。它們可以是框架相關(guān)的,也可以是獨(dú)立的。依賴于全局安裝的.NET運(yùn)行時(shí),依賴于框架的單個(gè)文件應(yīng)用程序可能很小。自包含的單文件應(yīng)用程序較大(由于帶有運(yùn)行時(shí)),但不需要作為安裝前步驟就安裝.NET運(yùn)行時(shí),因此可以正常工作。通常,依賴框架對(duì)開(kāi)發(fā)和企業(yè)環(huán)境有利,而對(duì)于ISV,獨(dú)立包含通常是更好的選擇。
.NET Core 3.1制作了一個(gè)單文件應(yīng)用程序版本。它將二進(jìn)制文件打包到一個(gè)文件中以進(jìn)行部署,然后將這些文件解壓縮到一個(gè)臨時(shí)目錄中以加載并執(zhí)行它們。在某些情況下,這種方法會(huì)更好,但是希望為5.0構(gòu)建的解決方案將是首選,并且會(huì)受到歡迎。??
可以使用以下命令來(lái)生成單文件應(yīng)用程序:
3. ClickOnce? ??
ClickOnce一直是流行的.NET部署選項(xiàng),歷史也比較悠久了。.NET Core 3.1和.NET 5.0 Windows應(yīng)用程序現(xiàn)在都已經(jīng)支持。? ?
??
以上是.NET 5.0 發(fā)布后的技術(shù)梳理和整理,.NET 5.0作為.NET技術(shù)棧上近幾年一個(gè)重量級(jí)的里程碑,是微軟.NET技術(shù) All in one 統(tǒng)一平臺(tái)的第一個(gè)版本。微軟從.NET 5.0 Preview 1就開(kāi)始在自己的網(wǎng)站上大規(guī)模使用(Bing.com、dot.net已升級(jí)并運(yùn)行了數(shù)個(gè)月),同時(shí)早期的.NET Core版本可以直接升級(jí)到.NET 5.0. 所以大家可以放心使用的,也推薦大家逐步遷移升級(jí)到.NET 5.0.
參考鏈接:
https://devblogs.microsoft.com/dotnet/announcing-net-5-0?WT.mc_id=DT-MVP-5003918
https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-5/#json?WT.mc_id=DT-MVP-5003918
https://blogs.windows.com/windowsdeveloper/2020/11/10/announcing-c-winrt-version-1-0-with-the-net-5-ga-release?WT.mc_id=DT-MVP-5003918
總結(jié)
以上是生活随笔為你收集整理的深度探秘.NET 5.0的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Github Actions 中 Ser
- 下一篇: 使用 .NET 5 体验大数据和机器学习