天天日夜夜添_精品国产99久久久久久人裸体 _成人app在线观看_日韩色网站

新聞資訊

    伴隨Windows 10推出的EDGE網(wǎng)頁(yè)瀏覽器,并沒(méi)有如微軟所愿,成為繼IE之后的流行網(wǎng)頁(yè)瀏覽器,當(dāng)中不不成功的原因很多,但“難用”會(huì)是非常大的原因,所以在一臺(tái)全新Windows系統(tǒng)的電腦上,EDGE不過(guò)是大家用來(lái)下載另外一個(gè)瀏覽器的工具(如果你保留有安裝包,甚至不用打開(kāi)它),所以微軟,他們?cè)?018年底確認(rèn)將會(huì)更換EDGE的內(nèi)核為Chromium,在經(jīng)過(guò)漫長(zhǎng)的一年beta后,現(xiàn)在新內(nèi)核的EDGE已經(jīng)正式上線了。

    在此前的EDGE瀏覽器中,微軟采用了自研的EdgeHTML渲染引擎,其實(shí)在性能上是要領(lǐng)先Chromium內(nèi)核的,但如今HTML、JavaScript和CCS語(yǔ)言對(duì)Chromium內(nèi)核支持更好,所以EDGE在打開(kāi)主流網(wǎng)頁(yè)時(shí)的實(shí)際表現(xiàn)不如Chromium內(nèi)核的瀏覽器,這是用戶所詬病的地方,所以無(wú)奈之下,微軟也只能選擇換用Google這個(gè)開(kāi)源的網(wǎng)頁(yè)渲染內(nèi)核。

    這個(gè)新版的EDGE瀏覽器除了更換新內(nèi)核,其它部分是與原來(lái)EDGE瀏覽器差不多的,包括UI界面、與Windows 10的優(yōu)化支持、微軟賬號(hào)的云同步等等功能都有保留,而且微軟還為新瀏覽器做了個(gè)新logo,采用漸變顏色的立體設(shè)計(jì),這與原來(lái)的扁平化風(fēng)格截然不同,據(jù)說(shuō)新logo其實(shí)是個(gè)浪花的,也就是大家俗稱(chēng)“上網(wǎng)沖浪”的意思在里面。

    目前微軟提供了Windows 10/8/8.1/7、macOS、Andorid和iOS多個(gè)平臺(tái)的EDGE瀏覽器提供下載安裝,你可以點(diǎn)這里獲取,但如果你不手動(dòng)安裝的話,在未來(lái)Windows 10系統(tǒng)更新時(shí)也是會(huì)把現(xiàn)有EDGE陸續(xù)自動(dòng)更新到這個(gè)版本,另外微軟還為UWP平臺(tái)的EDGE提供了ARM64版本的beta測(cè)試,這個(gè)需要快速通道的測(cè)試用戶才能收到。

    我們很高興今天.NET5.0正式發(fā)布。這是一個(gè)重要的版本—其中也包括了C# 9和F# 5大量新特性和優(yōu)秀的改進(jìn)。微軟和其他公司的團(tuán)隊(duì)已經(jīng)在生產(chǎn)和性能測(cè)試環(huán)境中開(kāi)始使用了。這些團(tuán)隊(duì)向我們反饋的結(jié)果比較令人滿意,它證明了對(duì)性能提升及降低Web應(yīng)用托管成本的機(jī)會(huì)有積極的表現(xiàn)。從預(yù)覽版1開(kāi)始,我們一直在5.0上運(yùn)行我們自己的網(wǎng)站。從我們目前的所見(jiàn)所聞來(lái)看,.NET5.0無(wú)需在升級(jí)上花費(fèi)太多的精力就能帶來(lái)巨大的價(jià)值。對(duì)于你的下一個(gè)應(yīng)用來(lái)說(shuō),這是一個(gè)很好的選擇,而且可以直接從早期的.NET Core版本升級(jí)。我們希望您在臺(tái)式機(jī)、筆記本電腦和云實(shí)例上正式開(kāi)始使用它。

    ASP.NET Core、EF Core、C#9和F#5也將在今天一同發(fā)布
    您可以下載.NET5.0,適用于Windows、MacOS和Linux,適用于x86、x64、Arm32和Arm64。

    • l 安裝程序和二進(jìn)制文件
    • l Docker 容器 images
    • l Linux package
    • l 發(fā)行說(shuō)明文檔
    • l 已知的問(wèn)題
    • l GitHub問(wèn)題跟蹤器
    • l .NET 5.0貢獻(xiàn)者

    對(duì)于Visual Studio用戶,您需要Visual Studio 16.8或更高的版本才能在Windows上使用.NET 5.0,在MacOS上使用最新版本的Visual Studio for Mac)。Visual Studio Code的C#擴(kuò)展也已經(jīng)支持.NET5.0和C#9。

    NET 5.0是我們的.NET統(tǒng)一之旅的第一個(gè)版本。我們構(gòu)建.NET 5.0是為了讓更多的開(kāi)發(fā)人員能夠?qū)⑺麄兊?NET Framework代碼和應(yīng)用程序遷移到.NET5.0。我們?cè)?.0中也做了很多前期工作,以便Xamarin開(kāi)發(fā)人員在發(fā)布.NET6.0時(shí)可以使用統(tǒng)一的.NET平臺(tái)。在后面的文章中會(huì)有更多關(guān)于.NET統(tǒng)一的內(nèi)容。

    這個(gè)版本是完全開(kāi)源的第五個(gè)主要的.NET版本。現(xiàn)在,在GitHub上的DotNet org中,有大量的個(gè)人和公司(包括.NET Foundation企業(yè)贊助商)作為一個(gè)大型社區(qū)在.NET的各個(gè)方面共同工作,.NET5.0中的改進(jìn)是許多人通過(guò)他們的努力及創(chuàng)新的想法構(gòu)成的結(jié)果,所有這些都超出了微軟對(duì)該項(xiàng)目的管理。為此,我們向所有為.NET 5.0(以及之前的版本)做出貢獻(xiàn)的人表示 “萬(wàn)分感謝”!
    我們?cè)缭?019年5月就引入了.NET5.0,當(dāng)時(shí)甚至設(shè)定了2020年11月的發(fā)布日期,結(jié)果我們?nèi)缙诎l(fā)布了,為此要感謝團(tuán)隊(duì)中的每一個(gè)人,是他們讓這一切成為現(xiàn)實(shí)! 2021年11月我們還將發(fā)布.NET 6.0,今后每年的11月我們都將發(fā)布新的.NET版本。

    .NET 5.0亮點(diǎn)

    在.NET5.0中有許多重要的改進(jìn):

    l .NET5.0已經(jīng)在dot.net和Bing.com上托管了幾個(gè)月,已經(jīng)經(jīng)過(guò)了數(shù)個(gè)月的實(shí)際測(cè)試。

    l 許多組件的性能都得到了極大的提高,在.NET5.0中的性能改進(jìn)、.NET5.0中的ARM64性能和GRPC中都有詳細(xì)描述。

    l C#9和F#5提供了新的語(yǔ)言改進(jìn),比如C# 9的頂級(jí)程序和記錄,而F# 5提供了交互式編程,.NET上函數(shù)式編程的性能得到了提升。

    l .NET庫(kù)增強(qiáng)了Json序列化、正則表達(dá)式和HTTP(HTTP 1.1、HTTP/2)的性能。

    l 改進(jìn)了GC、分層編譯和其他方面,P95延遲有所降低。

    l 通過(guò)ClickOnce客戶端發(fā)布應(yīng)用程序,單文件應(yīng)用程序,減小的容器映像大小以及添加的Server Core容器映像,應(yīng)用程序部署選項(xiàng)更好。

    l Windows Arm64和WebAssembly擴(kuò)展了平臺(tái)范圍。

    我已經(jīng)為.NET5.0寫(xiě)了很多Demo。您可以看一下這些.NET5.0示例,以了解更多關(guān)于新的C#9和庫(kù)特性的信息。
    平臺(tái)和Microsoft支持

    對(duì)于Windows、MacOS和Linux,.Net 5.0的平臺(tái)支持列表與.NET Core 3.1幾乎相同。如果您在受支持的操作系統(tǒng)上使用.NET Core 3.1,則應(yīng)該能夠在該操作系統(tǒng)的大部分版本上采用.NET 5.0。在.NET 5.0中,最重要的新增功能是Windows Arm64。

    .Net 5.0是當(dāng)前版本。這意味著它將在.NET6.0發(fā)布后的三個(gè)月內(nèi)得到支持。因此,我們預(yù)計(jì)到2022年2月中旬將支持.NET5.0。與.NET Core 3.1一樣,.NET6.0將是一個(gè)LTS版本,并將支持三年。
    平臺(tái)統(tǒng)一的愿景

    去年,我們分享了一個(gè)統(tǒng)一的.NET生態(tài)系統(tǒng)的愿景。它對(duì)您的價(jià)值在于,您將能夠使用同一組API、語(yǔ)言和工具來(lái)覆蓋廣泛的應(yīng)用類(lèi)型,其中包括移動(dòng)、云、桌面和物聯(lián)網(wǎng)。您可能已經(jīng)意識(shí)到,現(xiàn)在您已經(jīng)可以使用.NET面向廣泛的平臺(tái),但可能工具和API在Web和Mobile之間并不總是相同的,或者并不總是同時(shí)發(fā)布的。
    作為.NET5.0和6.0的一部分,我們正在將.NET的產(chǎn)品體驗(yàn)盡可能的進(jìn)行統(tǒng)一,同時(shí)使您能夠選擇您想要使用的.NET平臺(tái)的部分。如果你想以Mobile而不是WebAssembly為目標(biāo),你不需要下載WebAssembly工具,反之亦然。ASP.NET Core和WPF也是如此。您還可以通過(guò)更簡(jiǎn)單的方式從命令行獲取所需的所有.NET工具以及構(gòu)建和運(yùn)行時(shí)包。我們正在為.NET平臺(tái)組件提供包管理器體驗(yàn)(包括使用現(xiàn)有的包管理器)。這對(duì)于很多場(chǎng)景來(lái)說(shuō)都是很棒的。快速構(gòu)建開(kāi)發(fā)環(huán)境和CI / CD可能是最大的受益者。
    實(shí)現(xiàn)這一愿景的第一步是整合.NET repos,包括Mono的一個(gè)大子集。擁有一個(gè)用于運(yùn)行時(shí)和.NET庫(kù)的repo是在任何地方交付相同產(chǎn)品的前提條件。它還有助于進(jìn)行廣泛的更改,這些更改會(huì)影響運(yùn)行時(shí)和庫(kù),而這些庫(kù)以前是有repo邊界的。一些人擔(dān)心,大規(guī)模回購(gòu)將更難管理。事實(shí)證明并非如此。

    在.NET 5.0版本中,Blazor是利用回購(gòu)整合和.NET統(tǒng)一的最佳例子。Blazor WebAssembly的運(yùn)行時(shí)和庫(kù)現(xiàn)在是從合并的 DotNet/runtime repo所構(gòu)建的。例如,這意味著服務(wù)器上的Blazor WebAssembly和Blazor對(duì)List<T> 將使用完全相同的代碼。但在.NET5.0之前,Blazor并非如此。我們對(duì)Blazor WebAssembly采取的方法與我們?cè)?NET6.0中使用Xamarin的方法非常相似。

    .NET Framework仍然是受支持的Microsoft產(chǎn)品,并且每個(gè)新版本的Windows都將繼續(xù)支持它。我們?nèi)ツ晷家呀?jīng)停止向.NET Framework添加新功能,并完成了向.NET Core添加.NET Framework API。這意味著現(xiàn)在是考慮將您的.NET Framework應(yīng)用程序遷移到.NET Core的好機(jī)會(huì)。對(duì)于.NET Framework客戶端開(kāi)發(fā)人員,.NET5.0支持Windows窗體和WPF。我們從許多開(kāi)發(fā)人員那里聽(tīng)說(shuō),從.NET Framework移植非常簡(jiǎn)單。對(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)。WCF服務(wù)器和工作流用戶可以查看支持這些框架的社區(qū)項(xiàng)目。從.NET Framework移植到.NET Core文檔是一個(gè)很好的起點(diǎn)。這就是說(shuō),如果你對(duì)自己的體驗(yàn)滿意,那么讓你的應(yīng)用程序運(yùn)行在.NET Framework上是一個(gè)很好的方法。

    Windows團(tuán)隊(duì)正致力于研究Reunion作為UWP及其相關(guān)技術(shù)的下一步。我們一直在與Reunion團(tuán)隊(duì)合作,以確保.NET5.0及更高版本能夠很好地與WinUI和WebView2協(xié)同工作。

    讓我們來(lái)看看5.0版本中的新特性。

    語(yǔ)言

    C#9和F#5是.NET5.0版本的一部分,包含在.NET5.0 SDK中。Visual Basic也包含在5.0 SDK中。它不包括語(yǔ)言更改,但進(jìn)行了改進(jìn)以支持.NET Core上的Visual Basic應(yīng)用程序框架。
    C#源代碼生成器是一項(xiàng)重要的C#編譯器新特性。從技術(shù)上講,它們不是C#9的一部分,因?yàn)樗鼪](méi)有任何語(yǔ)言語(yǔ)法。請(qǐng)參閱新的C#源代碼生成器示例,幫助您開(kāi)始使用這一新功能。我們希望在.NET6.0及更高版本的.NET產(chǎn)品中更多地使用源代碼生成器。
    為了親身試用新版本,我們部分人決定更新DotNet/iot Repo,以使用新的C#9語(yǔ)法并以.NET5.0嘗試目標(biāo)。它使用頂級(jí)程序、記錄、模式和切換表達(dá)式。它也已更新,以利用.NET庫(kù)中完整的可為空的注釋集。我們還更新了.NET物聯(lián)網(wǎng)的文檔。我們將查看該repo中的幾個(gè)示例來(lái)探索C#9。

    LED-BLINK程序是一個(gè)不錯(cuò)的緊湊高級(jí)程序示例

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    using System;

    using System.Device.Gpio;

    using System.Threading;

    var pin=18;

    var lightTime=1000;

    var dimTime=200;

    Console.WriteLine($"Let's blink an LED!");

    using GpioController controller=new ();

    controller.OpenPin(pin, PinMode.Output);

    Console.WriteLine($"GPIO pin enabled for use: {pin}");

    // turn LED on and off

    while (true)

    {

    Console.WriteLine($"Light for {lightTime}ms");

    controller.Write(pin, PinValue.High);

    Thread.Sleep(lightTime);

    Console.WriteLine($"Dim for {dimTime}ms");

    controller.Write(pin, PinValue.Low);

    Thread.Sleep(dimTime);

    }

    您可以看到target-typed的使用以及new對(duì)controller變量的分配。。GpioController類(lèi)型僅在賦值的左側(cè)定義。類(lèi)型是在右手邊推斷出來(lái)的。這種新語(yǔ)法是var的另一種選擇,var的類(lèi)型只顯示在賦值的右側(cè),并通過(guò)關(guān)鍵字var在左側(cè)推斷。
    通過(guò)定義方法并利用在相同或其他文件中定義的類(lèi)型,頂級(jí)程序也可能增加復(fù)雜性。CharacterLcd示例演示了其中一些功能。
    邏輯和屬性模式

    C# 9包括對(duì)新模型的支持。您可以在如下代碼中看到關(guān)于這個(gè)邏輯模式的示例。

    1

    2

    3

    4

    5

    6

    var threshChoice=Console.ReadKey();

    Console.WriteLine();

    if (threshChoice.KeyChar is 'Y' or 'y')

    {

    TestThresholdAndInterrupt(ccs811);

    }

    另一種新模式是屬性模式。您可以在我的Mycroft信息訪問(wèn)6.0示例中看到幾個(gè)屬性檢查。以下代碼摘自PN532 RFID和NFC讀取器示例。

    1

    2

    3

    4

    if (pollingType is not { Length: <=15 })

    {

    return null;

    }

    此代碼測(cè)試pollingType(類(lèi)型為byte[]?)。為空或包含>15個(gè)字節(jié)。這是返回NULL之前需要測(cè)試的兩個(gè)錯(cuò)誤條件。也可以將此測(cè)試編寫(xiě)為pollingType為空或{Length:>15}。
    我想再給你看兩個(gè)模型。第一個(gè)是Mcp25xxx CAN總線的邏輯模式。

    1

    2

    3

    4

    5

    6

    public static byte GetRxBufferNumber(Address address)=> address switch

    {

    >=Address.RxB0D0 and <=Address.RxB0D7=> 0,

    >=Address.RxB1D0 and <=Address.RxB1D7=> 1,

    _=> throw new ArgumentException(nameof(address), $"Invalid address value {address}."),

    };

    第二個(gè)是Piezo蜂鳴器控制器中的邏輯模式。

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    if (element is not NoteElement noteElement)

    {

    // In case it's a pause element we have only just wait desired time.

    Thread.Sleep(durationInMilliseconds);

    }

    else

    {

    // In case it's a note element we play it.

    var frequency=GetFrequency(noteElement.Note, noteElement.Octave);

    _buzzer.PlayTone(frequency, (int)(durationInMilliseconds * 0.7));

    Thread.Sleep((int)(durationInMilliseconds * 0.3));

    }

    記錄

    C#9包括一個(gè)名為Record的新類(lèi)。與常規(guī)類(lèi)相比,它有許多優(yōu)點(diǎn),其中一半與更簡(jiǎn)潔的語(yǔ)法有關(guān)。以下記錄取自Bh1745 RGB傳感器綁定。

    1

    public record ChannelCompensationMultipliers(double Red, double Green, double Blue, double Clear);

    然后在同一文件中稍晚一點(diǎn)使用它,語(yǔ)法很熟悉:

    1

    ChannelCompensationMultipliers=new (2.2, 1.0, 1.8, 10.0);

    可為空性注釋的改進(jìn)

    現(xiàn)在,.NET庫(kù)完全為空性添加了注釋。這意味著如果您啟用nullability,您將從平臺(tái)獲得更多類(lèi)型信息來(lái)指導(dǎo)您使用該功能。目前,還沒(méi)有對(duì).NET文檔進(jìn)行完整的注釋。例如,String.IsNullOrEmpty(String)應(yīng)該被注釋為接受一個(gè)字符串?,而String.Split(Char[])的注釋是char[]?我們希望這個(gè)問(wèn)題很快就能解決。完整的信息可以在Soure.dot.net上找到,也可以通過(guò)Visual Studio中的F12元數(shù)據(jù)查找獲得。

    System.Device.Gpio和Iot.Device.Bindings包(這兩個(gè)包的版本都是1.1.0)也作為此版本的一部分進(jìn)行了注釋?zhuān)褂昧烁碌?NET5.0注釋。這兩個(gè)庫(kù)都是多目標(biāo)的,但是,我們使用5.0視圖為所有目標(biāo)生成注釋。

    我們還添加了新的注釋類(lèi)型。大型類(lèi)在從構(gòu)造函數(shù)調(diào)用的幫助器方法中實(shí)例化對(duì)象成員是很常見(jiàn)的。C#編譯器不能遵循對(duì)對(duì)象賦值的調(diào)用流程。當(dāng)退出構(gòu)造函數(shù)時(shí),它會(huì)認(rèn)為該成員為空,并將使用CS8618發(fā)出警告。MemberNotNull屬性可以解決此問(wèn)題。將該屬性應(yīng)用于幫助器方法。然后,編譯器將看到您設(shè)置了此值,并意識(shí)到該方法是從構(gòu)造函數(shù)調(diào)用的。MemberNotNullWhen類(lèi)似。

    您可以使用以下代碼在BMxx80溫度傳感器中看到MemberNotNull的示例。

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    [MemberNotNull(nameof(_calibrationData))]

    private void ReadCalibrationData()

    {

    switch (this)

    {

    case Bme280 _:

    _calibrationData=new Bme280CalibrationData();

    _controlRegister=(byte)Bmx280Register.CTRL_MEAS;

    break;

    case Bmp280 _:

    _calibrationData=new Bmp280CalibrationData();

    _controlRegister=(byte)Bmx280Register.CTRL_MEAS;

    break;

    case Bme680 _:

    _calibrationData=new Bme680CalibrationData();

    _controlRegister=(byte)Bme680Register.CTRL_MEAS;

    break;

    default:

    throw new Exception("Bmxx80 device not correctly configured. Could not find calibraton data.");

    }

    _calibrationData.ReadFromDevice(this);

    }

    實(shí)際代碼使用條件編譯。這是因?yàn)樵擁?xiàng)目是多目標(biāo)的,而該屬性僅在.NET5.0+中受支持。使用該屬性可以跳過(guò)運(yùn)行時(shí)檢查(在構(gòu)造函數(shù)中),否則將需要這些檢查來(lái)滿足可空性要求,就像早期的.NET版本一樣。
    工具類(lèi)

    我們改進(jìn)了Windows Forms 設(shè)計(jì)器,使其能在.NET5.0及更高版本中運(yùn)行,更改了支持WinRT的方式,并進(jìn)行了其他改進(jìn)。

    Windows窗體設(shè)計(jì)器

    Windows窗體設(shè)計(jì)器(用于.NET Core 3.1和.NET5.0)已在Visual Studio 16.8中進(jìn)行了更新,現(xiàn)在支持所有Windows窗體控件。設(shè)計(jì)器包括您指導(dǎo)的所有設(shè)計(jì)器功能,包括:拖放、選擇、移動(dòng)和調(diào)整大小、控件的剪切/復(fù)制/粘貼/刪除、與屬性窗口的集成、事件生成等。數(shù)據(jù)綁定和對(duì)更廣泛的第三方控件集的支持很快就會(huì)到來(lái)。


    .NET 5.0目標(biāo)框架

    在.NET5.0中,我們更改了用于目標(biāo)框架的方法。以下項(xiàng)目文件演示了新的.NET5.0目標(biāo)框架。

    1

    2

    3

    4

    5

    6

    7

    8

    <Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>

    <OutputType>Exe</OutputType>

    <TargetFramework>net5.0</TargetFramework>

    </PropertyGroup>

    </Project>

      

    新的net5.0表單比我們之前使用的樣式更緊湊、更直觀。此外,我們正在擴(kuò)展目標(biāo)框架以描述操作系統(tǒng)依賴關(guān)系。我們希望通過(guò).NET 6.0中的Xamarin定位iOS和Android,從而推動(dòng)了這一變化。
    net5.0netcoreapp3.1

    Windows桌面API(包括Windows窗體、WPF和WinRT)僅在面向net5.0-windows時(shí)可用。您可以指定操作系統(tǒng)版本,如net5.0-Windows7或net5.0-windows10.0.17763.0(適用于Windows 2018年10月更新)。如果您想要使用WinRT API,則需要瞄準(zhǔn)Windows 10版本。
    當(dāng)使用新的net5.0-windows tfm時(shí),跨平臺(tái)的場(chǎng)景可能會(huì)更具挑戰(zhàn)性。例如,System.Device.Gpio演示了一種用于管理Windows目標(biāo)框架的模式,例如,如果您希望避免為Windows構(gòu)建或避免在Linux上拉取Windows運(yùn)行時(shí)包。
    更新摘要:

    • l Net5.0是.NET5.0的新目標(biāo)框架Moniker (TFM)。
    • l Net5.0結(jié)合并取代了netcoreapp和netStandard tfms。
    • l Net5.0支持.NET Framework兼容模式。
    • l Net5.0-Windows將用于公開(kāi)特定于Windows的功能,包括Windows Forms、WPF和WinRT API。
    • l 特定于操作系統(tǒng)的TFMS可以包括操作系統(tǒng)版本號(hào),如net6.0-ios14。
    • l 像ASP.NET Core這樣的可移植API將可以在net5.0上使用。同樣的情況也適用于Net6.0的Xamarin Forms。

    Visual Studio 16.8中的模板仍然以.NET Core 3.1為目標(biāo),用于控制臺(tái)、WPF和Windows窗體應(yīng)用程序。ASP.NET模板已更新為支持.NET5.0。我們將在Visual Studio 16.9中更新其余模板的模板。

    WinRT Interop(重大更改)

    關(guān)于以Windows API為目標(biāo)的主題,我們已經(jīng)轉(zhuǎn)向了一個(gè)新的模型,將WinRT API作為.NET5.0的一部分來(lái)支持。這包括調(diào)用API(雙向;CLR<==>WinRT),兩個(gè)類(lèi)型系統(tǒng)之間的數(shù)據(jù)封送處理,以及要在類(lèi)型系統(tǒng)或ABI邊界上被同等對(duì)待的類(lèi)型的統(tǒng)一(即“投影類(lèi)型”;IEnumerable和IIterable就是例子)。

    現(xiàn)有的WinRT互操作系統(tǒng)已作為.NET5.0的一部分從.NET運(yùn)行時(shí)中移除。這是一個(gè)突破性的變化。這意味著使用WinRT和.NET Core 3.x的應(yīng)用程序和庫(kù)需要重新構(gòu)建,不能按原樣在.NET5.0上運(yùn)行。使用WinRT API的庫(kù)需要多目標(biāo)來(lái)管理.NET Core 3.1和.NET5.0之間的這種差異。
    展望未來(lái),我們將依靠WinRT團(tuán)隊(duì)在Windows中提供的新CsWinRT工具。它生成基于C#的WinRT互操作程序集,這些程序集可以通過(guò)NuGet交付。這正是Windows團(tuán)隊(duì)正在為Windows中的WinRT API所做的事情。任何想要使用WinRT(在Windows上)作為互操作系統(tǒng)的人都可以使用該工具,以將本機(jī)API公開(kāi)給.NET或?qū)?NETAPI公開(kāi)給本機(jī)代碼。
    CsWinRT工具在邏輯上類(lèi)似于tlbimp和tlbexp,但要好得多。TLB工具依賴于.NET運(yùn)行時(shí)中的大量COM互操作管道。CsWinRT工具只依賴于公共的.NETAPI。也就是說(shuō),C#9中的函數(shù)指針功能--在.NET5.0運(yùn)行時(shí)中部分實(shí)現(xiàn)了--在一定程度上是受到CsWinRT工具需求的啟發(fā)。
    這種新的WinRT互操作模型有幾個(gè)好處:

    • l 它可以獨(dú)立于.NET運(yùn)行時(shí)進(jìn)行開(kāi)發(fā)和改進(jìn)。
    • l 它與為iOS和Android等其他操作系統(tǒng)提供的基于工具的互操作系統(tǒng)是對(duì)稱(chēng)的。
    • l 該工具可以利用其他.NET特性(AOT、C#特性、IL鏈接),而這在以前的系統(tǒng)中不是一個(gè)選項(xiàng)。
    • l 簡(jiǎn)化了.NET運(yùn)行時(shí)代碼庫(kù)。

    使用WinRT API不需要添加NuGet引用。以Windows10TFM為目標(biāo)--剛才在.NET5.0TFM一節(jié)中已經(jīng)討論過(guò)了--已經(jīng)足夠了。如果您的目標(biāo)是.NET Core 3.1或更早版本,則需要引用WinRT包。您可以在System.Device.Gpio項(xiàng)目中看到此模式。
    原生導(dǎo)出

    很長(zhǎng)一段時(shí)間以來(lái),我們一直要求為調(diào)用.NET代碼的本機(jī)二進(jìn)制文件啟用導(dǎo)出。該場(chǎng)景的構(gòu)建塊是托管對(duì)UnManagedCeller sOnlyAttribute的API支持。
    此功能是創(chuàng)建更高級(jí)別體驗(yàn)的構(gòu)建塊。我們團(tuán)隊(duì)中的Aaron Robinson一直致力于一個(gè).NET Native Exports項(xiàng)目,該項(xiàng)目為將.NET組件發(fā)布為本機(jī)庫(kù)提供了更完整的體驗(yàn)。我們正在尋找有關(guān)此功能的反饋,以幫助決定是否應(yīng)將該方法包含在產(chǎn)品中。
    .NET原生導(dǎo)出項(xiàng)目使您能夠:

    • l 公開(kāi)自定義本機(jī)導(dǎo)出。
    • l 不需要像COM這樣的更高級(jí)別的互操作技術(shù)。
    • l 跨平臺(tái)工作。
    • 有一些現(xiàn)有的項(xiàng)目支持類(lèi)似的場(chǎng)景,例如:
    • l 不受管理的出口。
    • l DllExport

    多年來(lái),我們?cè)诒緳C(jī)應(yīng)用程序中看到了各種.NET托管模型。@rseanHall為此提出并實(shí)現(xiàn)了一種新穎的新模型,該模型利用了.NET應(yīng)用程序托管層提供的所有內(nèi)置應(yīng)用程序功能(特別是加載依賴項(xiàng)),同時(shí)允許從本機(jī)代碼調(diào)用自定義入口點(diǎn)。這在很多情況下都是完美的,可以想象在從本機(jī)應(yīng)用程序托管.NET組件的開(kāi)發(fā)人員中變得流行起來(lái)。這在以前是不存在的。謝謝你的貢獻(xiàn),@rseanHall。

    兩個(gè)主要PR:

    • l 啟用從應(yīng)用上下文調(diào)用Get_Runtime_Delegate。
    • l 實(shí)現(xiàn)HDT_GET_Function_POINTER

    事件管道
    事件管道是我們?cè)?NET Core 2.2中添加的一個(gè)新的子系統(tǒng)和API,它可以在任何操作系統(tǒng)上執(zhí)行性能和其他診斷調(diào)查。在.NET5.0中,事件管道已得到擴(kuò)展,使探查器能夠編寫(xiě)事件管道事件。此場(chǎng)景對(duì)于檢測(cè)以前依賴ETW(在Windows上)監(jiān)視應(yīng)用程序行為和性能的探查器至關(guān)重要。
    現(xiàn)在可以通過(guò)事件管道獲得程序集加載信息。這一改進(jìn)是使類(lèi)似的診斷功能(例如Fusion Log Viewer)成為.NET Framework的一部分的開(kāi)始。現(xiàn)在,您可以使用以下命令,使用Dotnet-TRACE來(lái)收集此信息:

    dotnet-trace collect --providers Microsoft-Windows-DotNETRuntime:4:4 -- ./MyApp –my-arg 1

    該工作流程在DotNet-TRACE文檔中進(jìn)行了說(shuō)明。您可以看到簡(jiǎn)單測(cè)試應(yīng)用程序的程序集加載信息。


    Microsoft.Extensions.Logging

    我們對(duì)Microsoft.Extensions.Logging庫(kù)中的控制臺(tái)日志提供程序進(jìn)行了改進(jìn)。現(xiàn)在,您可以實(shí)現(xiàn)自定義ConsoleForMatter來(lái)完全控制控制臺(tái)輸出的格式化和彩色化。格式化程序API通過(guò)實(shí)現(xiàn)VT-100(受大多數(shù)現(xiàn)代終端支持)轉(zhuǎn)義序列的子集來(lái)實(shí)現(xiàn)豐富的格式化。控制臺(tái)記錄器可以解析出不支持的終端上的轉(zhuǎn)義序列,允許您為所有終端編寫(xiě)一個(gè)格式化程序。

    除了對(duì)定制格式化程序的支持之外,我們還添加了一個(gè)內(nèi)置的JSON格式化程序,它可以將結(jié)構(gòu)化的JSON日志發(fā)送到控制臺(tái)。

    轉(zhuǎn)儲(chǔ)調(diào)試

    調(diào)試托管代碼需要了解托管對(duì)象和構(gòu)造。數(shù)據(jù)訪問(wèn)組件(DAC)是運(yùn)行時(shí)執(zhí)行引擎的子集,它了解這些構(gòu)造,可以在沒(méi)有運(yùn)行時(shí)的情況下訪問(wèn)這些托管對(duì)象。在Linux上收集的.Net Core進(jìn)程轉(zhuǎn)儲(chǔ)現(xiàn)在可以在Windows上使用WinDBG或DotNet Dump Analyze進(jìn)行分析。

    我們還添加了對(duì)從MacOS上運(yùn)行的.NET進(jìn)程捕獲ELF轉(zhuǎn)儲(chǔ)的支持。由于ELF不是MacOS上的本機(jī)可執(zhí)行文件格式(像lldb這樣的本機(jī)調(diào)試器不能處理這些轉(zhuǎn)儲(chǔ)),我們將其作為一種選擇加入的特性。要在MacOS上啟用轉(zhuǎn)儲(chǔ)收集支持,請(qǐng)?jiān)O(shè)置環(huán)境變量COMPLUS_DbgEnableElfDumpOnMacOS=1。生成的轉(zhuǎn)儲(chǔ)可以使用DotNet Dump Analyze進(jìn)行分析。

    打印環(huán)境信息

    隨著.NET擴(kuò)展了對(duì)新操作系統(tǒng)和芯片體系結(jié)構(gòu)的支持,人們有時(shí)想要一種打印環(huán)境信息的方式。我們創(chuàng)建了一個(gè)簡(jiǎn)單的.NET工具來(lái)完成此任務(wù),名為dotnet-runtimeinfo。

    您可以使用以下命令安裝和運(yùn)行該工具。

    1

    2

    dotnet tool install -f dotnet-runtimeinfo

    dotnet-runtimeinfo

    該工具為您的環(huán)境生成以下形式的輸出。

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    **.NET information

    Version: 5.0.0

    FrameworkDescription: .NET 5.0.0

    Libraries version: 5.0.0

    Libraries hash: cf258a14b70ad9069470a108f13765e0e5988f51

    **Environment information

    OSDescription: Linux 5.8.6-1-MANJARO-ARM #1 SMP Thu Sep 3 22:01:08 CEST 2020

    OSVersion: Unix 5.8.6.1

    OSArchitecture: Arm64

    ProcessorCount: 6

    **CGroup info**

    cfs_quota_us: -1

    memory.limit_in_bytes: 9223372036854771712

    memory.usage_in_bytes: 2740666368

    運(yùn)行時(shí)和庫(kù)
    在運(yùn)行時(shí)和庫(kù)中有很多改進(jìn)
    RyuJIT的代碼質(zhì)量改進(jìn)
    這個(gè)版本對(duì)JIT有很多改進(jìn),我在以前的.NET5.0預(yù)覽帖中分享了其中的許多改進(jìn)。在這篇文章中,我提升了來(lái)自社區(qū)的改變。

    • l 將xmm用于堆棧prolog-dotnet/Runtime#32538-更改為x86/x64 prolog零位調(diào)整代碼。改進(jìn):JSON;TechEmpower。致謝:本·亞當(dāng)斯。
    • l 用于ARM64的Vectorise位數(shù)組-Dotnet/Runtime#33749-BitArray類(lèi)已更新,包括使用ARM64內(nèi)部結(jié)構(gòu)的ARM64硬件加速實(shí)現(xiàn)。BitArray的性能改進(jìn)非常顯著。感謝@Gnbrkm41。
    • l 動(dòng)態(tài)通用詞典擴(kuò)展特性dotnet/運(yùn)行時(shí)#32270-一些(可能是大多數(shù)?)。基于改進(jìn)了運(yùn)行庫(kù)用來(lái)存儲(chǔ)有關(guān)泛型類(lèi)型和方法的信息的低級(jí)(本機(jī)代碼)字典的實(shí)現(xiàn),泛型的使用現(xiàn)在有了更好的性能(最初的性能發(fā)現(xiàn))。有關(guān)更多信息,請(qǐng)參見(jiàn)Perf:COLLECTION COUNT()在Core中比CLR慢。錯(cuò)誤報(bào)告歸功于@RealDotNetDave。
    • l Implementate Vector.Celing/Vector.Floor Dotnet/Runtime#31993-按照API提案,使用x64和Arm64內(nèi)部函數(shù)實(shí)現(xiàn)Vector.Celing/Vector.Floor。感謝@Gnbrkm41。
    • l TailCall助手的新的、更快的、可移植的實(shí)現(xiàn)。來(lái)源:Jakob Botsch Nielsen(.NET團(tuán)隊(duì)實(shí)習(xí)生)。來(lái)自@dsymetweet的反應(yīng)。
    • l 添加VectorTableList和TableVectorExtension內(nèi)部-Credit:@TamarChristinaArm(ARM Holdings)。
    • l 使用新的硬件內(nèi)部組件BSF/BSR-Credit@saucecontrol提高英特爾架構(gòu)性能。
    • l 實(shí)現(xiàn)向量{Size}.AllBitsSet-Credit@Gnbrkm41。
    • l 允許逃避一些邊界檢查-Credit@Nathan-Moore

    垃圾收集器GC
    在GC中進(jìn)行了以下改進(jìn)。

    • l 卡片標(biāo)記竊取-dotnet/coreclr#25986-服務(wù)器GC(在不同線程上)現(xiàn)在可以工作竊取,同時(shí)標(biāo)記由老一代對(duì)象持有的0/1類(lèi)對(duì)象。這意味著,在某些GC線程標(biāo)記時(shí)間比其他線程長(zhǎng)得多的情況下,短暫的GC暫停會(huì)更短。
    • l 引入固定對(duì)象堆-DotNet/Runtime#32283-添加固定對(duì)象堆(PoH)。這個(gè)新堆(大對(duì)象堆(LOH)的對(duì)等體)將允許GC單獨(dú)管理固定對(duì)象,從而避免固定對(duì)象對(duì)世代堆的負(fù)面影響。
    • l 允許從空閑列表分配大對(duì)象,同時(shí)后臺(tái)使用空閑列表清理啟用了SOH的LOH分配,而B(niǎo)GC正在清理SOH。以前,這只在LOH上使用段末尾空間。這允許更好地使用堆。
    • l 后臺(tái)GC掛起修復(fù)-dotnet/coreclr#27729-掛起修復(fù)減少了bgc和用戶線程掛起的時(shí)間。這減少了在GC發(fā)生之前掛起托管線程所需的總時(shí)間。Dotnet/coreclr#27578也促成了同樣的結(jié)果。
    • l 修正了擴(kuò)展塢中的命名組組處理,增加了對(duì)從命名組組讀取限制的支持。以前我們只讀全球版本。
    • l 優(yōu)化矢量化排序-Dotnet/Runtime#37159-GC中的矢量化標(biāo)記列表排序,減少了短暫的GC暫停時(shí)間(也包括Dotnet/Runtime#40613)。
    • l 世代感知分析-DotNet/Runtime#40322-世代感知分析,允許您確定哪些老一代對(duì)象保留在年輕一代對(duì)象上,從而使它們存活下來(lái),并導(dǎo)致短暫的GC暫停時(shí)間。
    • l 優(yōu)化分解GC堆內(nèi)存頁(yè)面-Dotnet/Runtime#35896-優(yōu)化分解,更好地分解邏輯,對(duì)于服務(wù)器GC來(lái)說(shuō),完全退出了“停止世界”階段,從而減少了阻塞GC的暫停時(shí)間。

    現(xiàn)在,GC通過(guò)EgGetGCMmemyInfo方法公開(kāi)最新集合的詳細(xì)信息。GCMmemyInfo結(jié)構(gòu)提供有關(guān)機(jī)器內(nèi)存、堆內(nèi)存和您指定的GC類(lèi)型的最新集合或最新集合的信息-臨時(shí)GC、完全阻塞GC或后臺(tái)GC。
    使用這個(gè)新API的最有可能的用例是日志記錄/監(jiān)視,或者向加載器平衡器指示機(jī)器應(yīng)該停止旋轉(zhuǎn)以請(qǐng)求完整的GC。它還可以通過(guò)減小緩存大小來(lái)避免容器硬限制。
    另一個(gè)小而有效的改變是將昂貴的重置內(nèi)存操作推遲到內(nèi)存不足的情況。我們預(yù)計(jì)策略中的這些更改將降低GC延遲(以及總體上的GC CPU使用率)。
    Windows ARM64

    現(xiàn)在,.NET應(yīng)用程序可以在Windows Arm64上本地運(yùn)行。在此之前,我們?cè)?NETCore3.0中添加了對(duì)Linux Arm64的支持(對(duì)Glibc和MUSL的支持)。使用.NET 5.0,您可以在Windows Arm64設(shè)備(如Surface Pro X)上開(kāi)發(fā)和運(yùn)行應(yīng)用程序。您已經(jīng)可以在Windows Arm64上運(yùn)行.NET Core和.NET Framework應(yīng)用程序,但需要通過(guò)x86仿真。這是可行的,但是原生ARM64執(zhí)行的性能要好得多。
    針對(duì)ARM64的MSI安裝程序是此版本的最終更改之一。您可以在下圖中看到.NET5.0SDK安裝程序。


    NET 5.0 SDK目前不包含Windows Arm64上的Windows桌面組件-Windows Forms和WPF。這一變化最初是在.NET5.0預(yù)覽版8中發(fā)布的。我們希望在5.0服務(wù)更新中添加Windows Arm64的Windows桌面包。我們目前還沒(méi)有可以分享的日期。在此之前,Windows Arm64支持SDK、控制臺(tái)和ASP.NET Core應(yīng)用程序,但Windows桌面組件不支持。

    ARM64性能

    一年多來(lái),我們?cè)谔岣逜RM64性能方面投入了大量資金。我們致力于使ARM64成為一個(gè)基于.NET的高性能平臺(tái)。這些改進(jìn)同樣適用于Windows和Linux。平臺(tái)可移植性和一致性一直是.NET令人信服的特點(diǎn)。這包括無(wú)論您在哪里使用.NET都能提供出色的性能。在.NET Core 3.x中,ARM64的功能與x64不相上下,但缺少一些關(guān)鍵的性能特性和投資。我們已經(jīng)在.NET5.0中解決了這個(gè)問(wèn)題,正如在.NET5.0中的ARM64性能中所描述的那樣。

    改進(jìn)之處在于:

    • l 調(diào)整ARM64的JIT優(yōu)化(示例)。
    • l 啟用并利用ARM64硬件特性(示例)。
    • l 調(diào)整ARM64庫(kù)中的關(guān)鍵性能算法(例如)。

    有關(guān)更多詳細(xì)信息,請(qǐng)參見(jiàn)在.NET5.0中提高Arm64性能。

    硬件內(nèi)部屬性是我們?cè)?NET Core3.0中添加的一個(gè)低級(jí)性能特性。當(dāng)時(shí),我們?cè)黾恿藢?duì)x86-64指令和芯片的支持。作為.NET5.0的一部分,我們正在擴(kuò)展該功能以支持ARM64。僅僅創(chuàng)建內(nèi)部結(jié)構(gòu)并不能提高性能。它們需要在性能關(guān)鍵型代碼中使用。我們?cè)?NET5.0的.NET庫(kù)中廣泛利用了Arm64的內(nèi)部特性。您也可以在自己的代碼中做到這一點(diǎn),盡管您需要熟悉CPU指令才能做到這一點(diǎn)。

    我將用一個(gè)類(lèi)比來(lái)解釋硬件內(nèi)部是如何工作的。在很大程度上,開(kāi)發(fā)人員依賴于.NET中內(nèi)置的類(lèi)型和API,比如string.Split或HttpClient。這些API通常通過(guò)P/Invoke功能利用本地操作系統(tǒng)API。P/Invoke支持高性能的本機(jī)互操作,并在.NET庫(kù)中為此廣泛使用。您可以自己使用相同的功能來(lái)調(diào)用本機(jī)API。硬件內(nèi)部功能類(lèi)似,不同之處在于它們不是調(diào)用操作系統(tǒng)API,而是使您能夠在代碼中直接使用CPU指令。它大致相當(dāng)于C++內(nèi)部函數(shù)的.NET版本。硬件本質(zhì)最好被認(rèn)為是一種CPU硬件加速功能。它們提供了非常實(shí)實(shí)在在的好處,現(xiàn)在是.NET庫(kù)性能基礎(chǔ)的關(guān)鍵部分,并負(fù)責(zé)您可以在.NET5.0性能帖子中讀到的許多好處。與C++相比,當(dāng).NET內(nèi)部函數(shù)被AOT編譯成隨時(shí)可以運(yùn)行的文件時(shí),內(nèi)部函數(shù)沒(méi)有運(yùn)行時(shí)性能損失。
    注意:Visual C++編譯器具有類(lèi)似的內(nèi)部特性。您可以直接將C++與.NET硬件內(nèi)部功能進(jìn)行比較,如果您在System.Rune me.Intrinsics.X86.Avx2、x64(AMD64)內(nèi)部功能列表和英特爾內(nèi)部功能指南中搜索_mm_i32ather_ep32,就可以看到這一點(diǎn)。你會(huì)看到很多相似之處。
    我們?cè)?.0中對(duì)ARM64的性能進(jìn)行了第一次重大投資,并將在后續(xù)版本中繼續(xù)這方面的努力。我們直接與ARM Holdings的工程師合作,確定產(chǎn)品改進(jìn)的優(yōu)先順序,并設(shè)計(jì)最充分利用ARMv8 ISA的算法。其中一些改進(jìn)將為ARM32帶來(lái)價(jià)值,然而,我們并沒(méi)有將獨(dú)特的努力應(yīng)用于ARM32。如果你使用的是Raspberry Pi,如果你安裝了新的Arm64版本的Raspberry Pi OS,你會(huì)享受到這些改進(jìn)。
    我們預(yù)計(jì)蘋(píng)果將在任何時(shí)候發(fā)布新的蘋(píng)果硅基Mac電腦。我們已經(jīng)有了針對(duì)Apple Silicon的.NET6.0的早期版本,并一直在與蘋(píng)果的工程師合作,幫助為該平臺(tái)優(yōu)化.NET。我們?cè)贏pple Silicon(Credit@Sickler)上也有一些早期的社區(qū)參與。

    P95+延遲
    我們看到越來(lái)越多的大型面向互聯(lián)網(wǎng)的網(wǎng)站和服務(wù)托管在.NET上。雖然有很多合理的關(guān)注點(diǎn)放在每秒請(qǐng)求數(shù)(RPS)指標(biāo)上,但我們發(fā)現(xiàn)沒(méi)有大的網(wǎng)站所有者問(wèn)我們這個(gè)問(wèn)題或要求數(shù)百萬(wàn)的RPS。然而,我們聽(tīng)說(shuō)了很多關(guān)于延遲的事情,特別是關(guān)于改善P95或P99延遲的問(wèn)題。通常,為站點(diǎn)配置的機(jī)器或核心的數(shù)量(以及最大的成本驅(qū)動(dòng)因素)是根據(jù)達(dá)到特定的P95指標(biāo)(而不是P50)來(lái)選擇的。我們認(rèn)為延遲是真正的“金錢(qián)指標(biāo)”。
    我們?cè)赟tack Overflow的朋友們?cè)诜窒硭麄兎?wù)上的數(shù)據(jù)方面做得很好。他們的一位工程師尼克·克雷弗(Nick Craver)最近分享了他們?cè)谶w移到.NET Core后看到的延遲改進(jìn):

    鎖定對(duì)象一直是GC性能的長(zhǎng)期挑戰(zhàn),特別是因?yàn)樗鼈兗铀?或?qū)е?內(nèi)存碎片。我們?yōu)楣潭▽?duì)象添加了一個(gè)新的GC堆。固定對(duì)象堆基于這樣的假設(shè),即進(jìn)程中固定的對(duì)象非常少,但它們的存在會(huì)造成不成比例的性能挑戰(zhàn)。將固定對(duì)象(尤其是那些由.NET庫(kù)作為實(shí)現(xiàn)細(xì)節(jié)創(chuàng)建的對(duì)象)移動(dòng)到一個(gè)獨(dú)特的區(qū)域是有意義的,這樣會(huì)使世代GC堆中只有很少的固定對(duì)象,甚至沒(méi)有固定對(duì)象,因此性能會(huì)大大提高。
    最近,我們一直在應(yīng)對(duì)大中華區(qū)長(zhǎng)期存在的挑戰(zhàn)。DotNet/Runtime#2795應(yīng)用了一種新的GC靜態(tài)掃描方法,在確定GC堆對(duì)象的活躍度時(shí)避免了鎖爭(zhēng)用。Dotnet/Runtime#25986使用了一種新算法,用于在垃圾收集的標(biāo)記階段跨核心平衡GC工作,這應(yīng)該會(huì)增加大堆垃圾收集的吞吐量,進(jìn)而減少延遲。

    提高分層編譯的性能

    我們一直致力于改進(jìn)多版本的分層編譯。我們繼續(xù)將其視為一個(gè)關(guān)鍵的性能特性,無(wú)論是啟動(dòng)性能還是穩(wěn)態(tài)性能。在這個(gè)版本中,我們對(duì)分層編譯做了兩大改進(jìn)。
    分層編譯的主要機(jī)制是調(diào)用計(jì)數(shù)。一旦一個(gè)方法被調(diào)用n次,運(yùn)行庫(kù)就會(huì)要求JIT以更高的質(zhì)量重新編譯該方法。從我們最早的性能分析中,我們知道呼叫計(jì)數(shù)機(jī)制太慢,但沒(méi)有看到一個(gè)簡(jiǎn)單的方法來(lái)解決這個(gè)問(wèn)題。作為.NET5.0的一部分,我們改進(jìn)了分層JIT編譯使用的調(diào)用計(jì)數(shù)機(jī)制,以平滑啟動(dòng)時(shí)的性能。在過(guò)去的版本中,我們看到了在進(jìn)程生命周期的前10-15秒(主要是Web服務(wù)器)中出現(xiàn)的不可預(yù)測(cè)的性能報(bào)告。這個(gè)問(wèn)題現(xiàn)在應(yīng)該得到解決。
    我們發(fā)現(xiàn)的另一個(gè)性能挑戰(zhàn)是對(duì)帶有循環(huán)的方法使用分層編譯。根本問(wèn)題是,您可以使用一個(gè)循環(huán)多次的冷方法(只調(diào)用一次或幾次;$lt;n)。我們稱(chēng)這種病態(tài)場(chǎng)景為“冷方法;熱循環(huán)”。很容易想象這種情況會(huì)發(fā)生在應(yīng)用程序的Main方法中。因此,默認(rèn)情況下,我們禁用了具有循環(huán)的方法的分層編譯。相反,我們?cè)试S應(yīng)用程序選擇使用帶循環(huán)的分層編譯。PowerShell是在看到某些場(chǎng)景的高個(gè)位數(shù)性能改進(jìn)后選擇這樣做的應(yīng)用程序。
    為了更好地處理具有循環(huán)的方法,我們實(shí)現(xiàn)了棧上替換(OSR)。這類(lèi)似于Java虛擬機(jī)具有的同名功能。OSR使當(dāng)前正在運(yùn)行的方法執(zhí)行的代碼能夠在方法執(zhí)行過(guò)程中重新編譯,而這些方法是活動(dòng)的“堆棧上”。這一功能目前還處于試驗(yàn)階段和選擇加入階段,并且僅在x64上。
    要使用OSR,必須啟用多項(xiàng)功能。PowerShell項(xiàng)目文件是一個(gè)很好的起點(diǎn)。您會(huì)注意到,分層編譯和所有快速JIT功能都已啟用。此外,需要將COMPLUS_TC_OnStackReplace環(huán)境變量設(shè)置為1。
    或者,您也可以設(shè)置以下兩個(gè)環(huán)境變量,假設(shè)所有其他設(shè)置都有其缺省值:
    COMPLUS_TC_QuickJitForLoops=1。
    COMPLUS_TC_OnStackReplace=1。
    我們不打算在.NET5.0中默認(rèn)啟用OSR,也還沒(méi)有決定是否會(huì)在生產(chǎn)中支持它。

    在Windows上支持ICU

    我們使用ICU庫(kù)來(lái)支持Unicode和全球化,以前只在Linux和MacOS上使用。我們現(xiàn)在在Windows 10上使用相同的庫(kù)。這一更改使得全球化API的行為在Windows 10、MacOS和Linux之間保持一致,例如特定于區(qū)域性的字符串比較。我們還將ICU與Blazor WebAssembly配合使用。

    將System.DirectoryServices.Protooles擴(kuò)展到Linux和MacOS

    我們一直在添加對(duì)System.DirectoryServices.Protooles的跨平臺(tái)支持。這包括對(duì)Linux的支持和對(duì)MacOS的支持。Windows支持是預(yù)先存在的。
    協(xié)議是一個(gè)比System.DirectoryServices更低級(jí)的API,可以支持(或可以用來(lái)支持)更多場(chǎng)景。System.DirectoryServices包含僅限Windows的概念/實(shí)現(xiàn),因此它不是跨平臺(tái)的明顯選擇。這兩個(gè)API集都支持控制目錄服務(wù)服務(wù)器并與其交互,如LDAP或Active Directory。

    System.Text.Json

    System.Text.Json在.NET5.0中得到了顯著改進(jìn),以提高性能和可靠性,并使熟悉Newtonsoft.Json的人們更容易采用。它還支持將JSON對(duì)象反序列化為記錄。
    如果您正在考慮使用System.Text.Json作為Newtonsoft.Json的替代方案,您應(yīng)該查看遷移指南。本指南闡明了這兩個(gè)API之間的關(guān)系。Json旨在涵蓋許多與Newtonsoft.Json相同的場(chǎng)景,但它并不是要替代流行的JSON庫(kù),也不是要實(shí)現(xiàn)與流行的JSON庫(kù)相同的功能。我們?cè)噲D在性能和可用性之間保持平衡,在我們的設(shè)計(jì)選擇中偏向于性能。

    HttpClient擴(kuò)展方法

    JsonSerializer擴(kuò)展方法現(xiàn)在在HttpClient上公開(kāi),極大地簡(jiǎn)化了這兩個(gè)API的結(jié)合使用。這些擴(kuò)展方法消除了復(fù)雜性,并為您處理了各種場(chǎng)景,包括處理內(nèi)容流和驗(yàn)證內(nèi)容媒體類(lèi)型。Steve Gordon很好地解釋了在System.Net.Http.Json中使用HttpClient發(fā)送和接收J(rèn)SON的好處。
    下面的示例將天氣預(yù)報(bào)JSON數(shù)據(jù)反序列化為Forecast記錄,使用新的

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    using System;

    using System.Net.Http;

    using System.Net.Http.Json;

    string serviceURL="https://localhost:5001/WeatherForecast";

    HttpClient client=new();

    Forecast[] forecasts=await client.GetFromJsonAsync<Forecast[]>(serviceURL);

    foreach(Forecast forecast in forecasts)

    {

    Console.WriteLine($"{forecast.Date}; {forecast.TemperatureC}C; {forecast.Summary}");

    }

    // {"date":"2020-09-06T11:31:01.923395-07:00","temperatureC":-1,"temperatureF":31,"summary":"Scorching"}

    public record Forecast(DateTime Date, int TemperatureC, int TemperatureF, string Summary);

    這段代碼很緊湊!它依賴于C#9中的頂級(jí)程序和記錄以及新的GetFromJsonAsync<T>()擴(kuò)展方法。在如此接近的情況下使用Foreach和Await可能會(huì)讓您懷疑,我們是否要添加對(duì)JSON對(duì)象流的支持。我真的希望如此。
    您可以在自己的機(jī)器上嘗試此功能。以下.NET SDK命令將使用WebAPI模板創(chuàng)建天氣預(yù)報(bào)服務(wù)。默認(rèn)情況下,它將在以下網(wǎng)址公開(kāi)服務(wù):https://localhost:5001/WeatherForecast.。這與示例中使用的URL相同。

    1

    2

    3

    rich@thundera ~ % dotnet new webapi -o webapi

    rich@thundera ~ % cd webapi

    rich@thundera webapi % dotnet run

    確保您已經(jīng)運(yùn)行了DotNet dev-certs https--首先信任,否則客戶端和服務(wù)器之間的握手將不起作用。如果遇到問(wèn)題,請(qǐng)參閱信任ASP.NET核心HTTPS開(kāi)發(fā)證書(shū)。
    然后,您可以運(yùn)行上一個(gè)示例。

    1

    2

    3

    4

    5

    6

    7

    8

    rich@thundera ~ % git clone https://gist.github.com/3b41d7496f2d8533b2d88896bd31e764.git weather-forecast

    rich@thundera ~ % cd weather-forecast

    rich@thundera weather-forecast % dotnet run

    9/9/2020 12:09:19 PM; 24C; Chilly

    9/10/2020 12:09:19 PM; 54C; Mild

    9/11/2020 12:09:19 PM; -2C; Hot

    9/12/2020 12:09:19 PM; 24C; Cool

    9/13/2020 12:09:19 PM; 45C; Balmy

    改進(jìn)了對(duì)不可變類(lèi)型的支持
    定義不可變類(lèi)型有多種模式。記錄只是最新的記錄。JsonSerializer現(xiàn)在支持不可變類(lèi)型。
    在本例中,您將看到帶有不可變結(jié)構(gòu)的序列化。

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    using System;

    using System.Text.Json;

    using System.Text.Json.Serialization;

    var json="{"date":"2020-09-06T11:31:01.923395-07:00","temperatureC":-1,"temperatureF":31,"summary":"Scorching"} ";

    var options=new JsonSerializerOptions()

    {

    PropertyNameCaseInsensitive=true,

    IncludeFields=true,

    PropertyNamingPolicy=JsonNamingPolicy.CamelCase

    };

    var forecast=JsonSerializer.Deserialize<Forecast>(json, options);

    Console.WriteLine(forecast.Date);

    Console.WriteLine(forecast.TemperatureC);

    Console.WriteLine(forecast.TemperatureF);

    Console.WriteLine(forecast.Summary);

    var roundTrippedJson=JsonSerializer.Serialize<Forecast>(forecast, options);

    Console.WriteLine(roundTrippedJson);

    public struct Forecast{

    public DateTime Date {get;}

    public int TemperatureC {get;}

    public int TemperatureF {get;}

    public string Summary {get;}

    [JsonConstructor]

    public Forecast(DateTime date, int temperatureC, int temperatureF, string summary)=> (Date, TemperatureC, TemperatureF, Summary)=(date, temperatureC, temperatureF, summary);

    }

      

    注意:JsonConstructor屬性是指定要與結(jié)構(gòu)一起使用的構(gòu)造函數(shù)所必需的。對(duì)于類(lèi),如果只有一個(gè)構(gòu)造函數(shù),則不需要該屬性。記錄也是如此。
    它會(huì)產(chǎn)生以下輸出:

     

    1

    2

    3

    4

    5

    6

    rich@thundera jsonserializerimmutabletypes % dotnet run

    9/6/2020 11:31:01 AM

    -1

    31

    Scorching

    {"date":"2020-09-06T11:31:01.923395-07:00","temperatureC":-1,"temperatureF":31,"summary":"Scorching"}

    支持記錄
    JsonSerializer對(duì)記錄的支持幾乎與我剛才向您展示的對(duì)不可變類(lèi)型的支持相同。我想在這里展示的不同之處在于將JSON對(duì)象反序列化為一個(gè)記錄,該記錄公開(kāi)了一個(gè)參數(shù)化的構(gòu)造函數(shù)和一個(gè)可選的init屬性。
    以下是程序片段,包括Record定義:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    using System;

    using System.Text.Json;

    Forecast forecast=new(DateTime.Now, 40)

    {

    Summary="Hot!"

    };

    string forecastJson=JsonSerializer.Serialize<Forecast>(forecast);

    Console.WriteLine(forecastJson);

    Forecast? forecastObj=JsonSerializer.Deserialize<Forecast>(forecastJson);

    Console.Write(forecastObj);

    public record Forecast (DateTime Date, int TemperatureC)

    {

    public string? Summary {get; init;}

    };

    它會(huì)產(chǎn)生以下輸出:

    1

    2

    3

    rich@thundera jsonserializerrecords % dotnet run

    {"Date":"2020-09-12T18:24:47.053821-07:00","TemperatureC":40,"Summary":"Hot!"}

    Forecast { Date=9/12/2020 6:24:47 PM, TemperatureC=40, Summary=Hot! }

    改進(jìn)了對(duì)Dictionary<K,V>的支持

    JsonSerializer現(xiàn)在支持使用非字符串鍵的字典。您可以在下面的示例中看到這是什么樣子。在.NET Core 3.0中,此代碼進(jìn)行編譯,但會(huì)引發(fā)NotSupportdException異常。

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    using System;

    using System.Collections.Generic;

    using System.Text.Json;

    Dictionary<int, string> numbers=new ()

    {

    {0, "zero"},

    {1, "one"},

    {2, "two"},

    {3, "three"},

    {5, "five"},

    {8, "eight"},

    {13, "thirteen"},

    {21, "twenty one"},

    {34, "thirty four"},

    {55, "fifty five"},

    };

    var json=JsonSerializer.Serialize<Dictionary<int, string>>(numbers);

    Console.WriteLine(json);

    var dictionary=JsonSerializer.Deserialize<Dictionary<int, string>>(json);

    Console.WriteLine(dictionary[55]);

    它會(huì)產(chǎn)生以下輸出。

    1

    2

    3

    rich@thundera jsondictionarykeys % dotnet run

    {"0":"zero","1":"one","2":"two","3":"three","5":"five","8":"eight","13":"thirteen","21":"twenty one","34":"thirty four","55":"fifty five"}

    fifty five

    對(duì)字段的支持

    JsonSerializer現(xiàn)在支持字段。這一變化是由@YohDeadfall貢獻(xiàn)的。謝謝!。
    您可以在下面的示例中看到這是什么樣子。在.NET Core 3.0中,JsonSerializer無(wú)法序列化或反序列化使用字段的類(lèi)型。對(duì)于具有字段且無(wú)法更改的現(xiàn)有類(lèi)型,這是一個(gè)問(wèn)題。有了這一變化,這就不再是問(wèn)題了。

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    using System;

    using System.Text.Json;

    var json="{\"date\":\"2020-09-06T11:31:01.923395-07:00\",\"temperatureC\":-1,\"temperatureF\":31,\"summary\":\"Scorching\"} ";

    var options=new JsonSerializerOptions()

    {

    PropertyNameCaseInsensitive=true,

    IncludeFields=true,

    PropertyNamingPolicy=JsonNamingPolicy.CamelCase

    };

    var forecast=JsonSerializer.Deserialize<Forecast>(json, options);

    Console.WriteLine(forecast.Date);

    Console.WriteLine(forecast.TemperatureC);

    Console.WriteLine(forecast.TemperatureF);

    Console.WriteLine(forecast.Summary);

    var roundTrippedJson=JsonSerializer.Serialize<Forecast>(forecast, options);

    Console.WriteLine(roundTrippedJson);

    public class Forecast{

    public DateTime Date;

    public int TemperatureC;

    public int TemperatureF;

    public string Summary;

    }

    它會(huì)產(chǎn)生以下輸出。

    1

    2

    3

    4

    5

    6

    rich@thundera jsonserializerfields % dotnet run

    9/6/2020 11:31:01 AM

    -1

    31

    Scorching

    {"date":"2020-09-06T11:31:01.923395-07:00","temperatureC":-1,"temperatureF":31,"summary":"Scorching"}

    保留JSON對(duì)象圖中的引用

    JsonSerializer增加了對(duì)在JSON對(duì)象圖中保留(循環(huán))引用的支持。它通過(guò)存儲(chǔ)ID來(lái)實(shí)現(xiàn)這一點(diǎn),當(dāng)JSON字符串被反序列化為對(duì)象時(shí),這些ID可以重新組成。

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    52

    53

    54

    using System;

    using System.Collections.Generic;

    using System.Text.Json;

    using System.Text.Json.Serialization;

    Employee janeEmployee=new()

    {

    Name="Jane Doe",

    YearsEmployed=10

    };

    Employee johnEmployee=new()

    {

    Name="John Smith"

    };

    janeEmployee.Reports=new List<Employee> { johnEmployee };

    johnEmployee.Manager=janeEmployee;

    JsonSerializerOptions options=new()

    {

    // NEW: globally ignore default values when writing null or default

    DefaultIgnoreCondition=JsonIgnoreCondition.WhenWritingDefault,

    // NEW: globally allow reading and writing numbers as JSON strings

    NumberHandling=JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString,

    // NEW: globally support preserving object references when (de)serializing

    ReferenceHandler=ReferenceHandler.Preserve,

    IncludeFields=true, // NEW: globally include fields for (de)serialization

    WriteIndented=true,};

    string serialized=JsonSerializer.Serialize(janeEmployee, options);

    Console.WriteLine($"Jane serialized: {serialized}");

    Employee janeDeserialized=JsonSerializer.Deserialize<Employee>(serialized, options);

    Console.Write("Whether Jane's first report's manager is Jane: ");

    Console.WriteLine(janeDeserialized.Reports[0].Manager==janeDeserialized);

    public class Employee

    {

    // NEW: Allows use of non-public property accessor.

    // Can also be used to include fields "per-field", rather than globally with JsonSerializerOptions.

    [JsonInclude]

    public string Name { get; internal set; }

    public Employee Manager { get; set; }

    public List<Employee> Reports;

    public int YearsEmployed { get; set; }

    // NEW: Always include when (de)serializing regardless of global options

    [JsonIgnore(Condition=JsonIgnoreCondition.Never)]

    public bool IsManager=> Reports?.Count > 0;

    }

    性能

    在.NET5.0中,JsonSerializer的性能得到了顯著提高。Stephen Toub在他的.NET5帖子中談到了JsonSerializer的一些性能改進(jìn)。我還在.NET5.0RC1文章中更詳細(xì)地介紹了Json的性能。

    應(yīng)用程序部署

    在編寫(xiě)或更新應(yīng)用程序之后,您需要部署它以使您的用戶受益。這可能是到Web服務(wù)器、云服務(wù)或客戶端計(jì)算機(jī),也可能是使用Azure DevOps或GitHub操作等服務(wù)的CI/CD流的結(jié)果。
    我們努力提供一流的部署功能,自然地與應(yīng)用程序類(lèi)型保持一致。對(duì)于.NET5.0,我們專(zhuān)注于改進(jìn)單文件應(yīng)用程序,減少停靠多階段構(gòu)建的容器大小,并為使用.NET Core部署ClickOnce應(yīng)用程序提供更好的支持。

    容器

    我們認(rèn)為容器是最重要的云趨勢(shì),并在這方面投入了大量資金。我們正在以多種方式投資容器,在.NET軟件堆棧的多個(gè)級(jí)別上。首先是我們對(duì)基本面的投資,這越來(lái)越多地受到容器場(chǎng)景和部署容器應(yīng)用的開(kāi)發(fā)者的影響。
    我們正在讓與集裝箱管弦樂(lè)團(tuán)的合作變得更容易。我們已經(jīng)添加了OpenTelemeter支持,這樣您就可以從您的應(yīng)用程序中捕獲分布式跟蹤和指標(biāo)。DotNet-monitor是一種新工具,旨在作為從.NET進(jìn)程訪問(wèn)診斷信息的主要方式。特別是,我們已經(jīng)開(kāi)始構(gòu)建dotnet-monitor的容器變體,您可以將其用作應(yīng)用程序側(cè)車(chē)。最后,我們正在構(gòu)建DotNet/Tye,以此來(lái)提高微服務(wù)開(kāi)發(fā)人員的工作效率,包括開(kāi)發(fā)和部署到Kubernetes環(huán)境。
    NET運(yùn)行時(shí)現(xiàn)在支持cgroup v2,我們預(yù)計(jì)它將在2020年后成為與容器相關(guān)的重要API。Docker目前使用的是cgroup v1(已經(jīng)被.NET支持)。相比之下,cgroup v2比cgroup v1更簡(jiǎn)單、更高效、更安全。您可以通過(guò)我們2019年Docker更新了解更多關(guān)于cgroup和Docker資源限制的信息。Linux發(fā)行版和容器運(yùn)行時(shí)正在添加對(duì)cgroup v2的支持。一旦cgroup v2環(huán)境變得更加普遍,.Net 5.0將在cgroup v2環(huán)境中正常工作。這歸功于Omair Majid,他在Red Hat支持.NET。
    除了Nano Server,我們現(xiàn)在還發(fā)布Windows Server Core鏡像。我們添加了Server Core,因?yàn)槲覀兪盏搅丝蛻舻姆答仯麄兿胍粋€(gè)與Windows Server完全兼容的.NET映像。如果你需要這個(gè),那么這張新照片就是為你準(zhǔn)備的。支持Windows Server 2019長(zhǎng)期服務(wù)渠道(LTSC)、.NET5.0和x64的組合。我們還進(jìn)行了其他更改,以減小Windows服務(wù)器核心映像的大小。這些改進(jìn)帶來(lái)了很大的不同,但都是在Windows Server 2019發(fā)布之后做出的。然而,它們將使下一個(gè)Windows Server LTSC版本受益。
    作為使用“.NET”作為產(chǎn)品名稱(chēng)的一部分,我們現(xiàn)在將.NET Core 2.1、3.1和.NET5.0鏡像發(fā)布到mcr.microsoft.com/dotnet系列的Repos中,而不是發(fā)布到mcr.microsoft.com/dotnet/core。我們將繼續(xù)將.NET Core 2.1和3.1雙重發(fā)布到以前的位置,同時(shí)支持這些版本。.Net 5.0圖像將僅發(fā)布到新位置。請(qǐng)相應(yīng)地更新您的From語(yǔ)句和腳本。
    作為.NET5.0的一部分,我們將SDK鏡像重新建立在ASP.NET鏡像之上,而不是構(gòu)建包-dep,以顯著減小您在多階段構(gòu)建場(chǎng)景中拉取的聚合鏡像的大小。
    此更改對(duì)于多階段構(gòu)建有以下好處,其中包含一個(gè)示例Dockerfile:
    Ubuntu 20.04 Focus的多階段構(gòu)建成本:

    Pull Image

    Before

    After

    sdk:5.0-focal

    268 MB

    232 MB

    aspnet:5.0-focal

    64 MB

    10 KB (manifest only)

    減少了約: 100 MB (-30%)

    Debian 10 Buster的多階段構(gòu)建成本:

    Pull Image

    Before

    After

    sdk:5.0

    280 MB

    218 MB

    aspnet:5.0

    84 MB

    4 KB (manifest only)

    減少了約: 146 MB (-40%)

    有關(guān)更多詳細(xì)信息,請(qǐng)參見(jiàn)Dotnet/Dotnet-docker#1814。
    此更改有助于多階段構(gòu)建,其中SDK和您的目標(biāo)aspnet或運(yùn)行時(shí)鏡像的版本相同(我們預(yù)計(jì)這是常見(jiàn)的情況)。在進(jìn)行此更改時(shí),(例如)aspnet拉入將是不可行的,因?yàn)槟鷮⑼ㄟ^(guò)最初的SDK拉入拉出aspnet層。
    我們對(duì)阿爾卑斯和Nano服務(wù)器做了類(lèi)似的更改。阿爾卑斯和Nano服務(wù)器都沒(méi)有Buildpack-dep鏡像。但是,阿爾卑斯和Nano Server的SDK鏡像之前并不是在ASP.NET鏡像之上構(gòu)建的。我們解決了這個(gè)問(wèn)題。你將會(huì)看到阿爾卑斯和Nano服務(wù)器以及5.0版本在多階段構(gòu)建方面都獲得了巨大的成功。

    單文件應(yīng)用程序

    單個(gè)文件應(yīng)用程序作為單個(gè)文件發(fā)布和部署。該應(yīng)用程序及其依賴項(xiàng)都包含在該文件中。當(dāng)應(yīng)用程序運(yùn)行時(shí),依賴項(xiàng)直接從該文件加載到內(nèi)存中(不會(huì)影響性能)。
    在.NET5.0中,單文件應(yīng)用程序主要集中在Linux上(稍后會(huì)詳細(xì)介紹)。它們可以是依賴于框架的,也可以是獨(dú)立的。依賴于全球安裝的.NET運(yùn)行時(shí),依賴于框架的單個(gè)文件應(yīng)用程序可能非常小。自包含的單文件應(yīng)用程序較大(由于帶有運(yùn)行庫(kù)),但不需要在安裝前安裝.NET運(yùn)行庫(kù),因此可以直接運(yùn)行。一般來(lái)說(shuō),依賴于框架對(duì)開(kāi)發(fā)和企業(yè)環(huán)境都有好處,而對(duì)于ISV來(lái)說(shuō),自包含通常是更好的選擇。
    我們用.NET Core 3.1制作了一個(gè)版本的單文件應(yīng)用程序。它將二進(jìn)制文件打包到單個(gè)文件中進(jìn)行部署,然后將這些文件解壓縮到一個(gè)臨時(shí)目錄中以加載和執(zhí)行它們。在某些情況下,這種方法可能會(huì)更好,但我們希望我們?yōu)?.0構(gòu)建的解決方案會(huì)更好,這是一個(gè)值得歡迎的改進(jìn)。
    要?jiǎng)?chuàng)建真正的單一文件解決方案,我們需要克服多個(gè)障礙。關(guān)鍵任務(wù)是創(chuàng)建一個(gè)更復(fù)雜的應(yīng)用程序捆綁器,并教導(dǎo)運(yùn)行庫(kù)從二進(jìn)制資源加載程序集。我們還遇到了一些無(wú)法逾越的障礙。
    在所有平臺(tái)上,我們都有一個(gè)稱(chēng)為“apphost”的組件。這是成為可執(zhí)行文件的文件,例如Windows上的myapp.exe或基于Unix的平臺(tái)上的./myapp。對(duì)于單一文件應(yīng)用程序,我們創(chuàng)建了一個(gè)新的apphost,我們稱(chēng)之為“超級(jí)主機(jī)”。它具有與常規(guī)apphost相同的角色,但還包括運(yùn)行時(shí)的靜態(tài)鏈接副本。超級(jí)主機(jī)是我們單一文件方法的一個(gè)基本設(shè)計(jì)點(diǎn)。這個(gè)模型就是我們?cè)趲в?NET5.0的Linux上使用的模型。由于各種操作系統(tǒng)的限制,我們無(wú)法在Windows或MacOS上實(shí)現(xiàn)這種方法。我們?cè)赪indows或MacOS上沒(méi)有超級(jí)主機(jī)。在這些操作系統(tǒng)上,本地運(yùn)行時(shí)二進(jìn)制文件(大約3個(gè))位于單個(gè)文件應(yīng)用程序旁邊(導(dǎo)致“不是單個(gè)文件”)。我們將在.NET6.0中重新討論這種情況,然而,我們預(yù)計(jì)我們遇到的問(wèn)題仍然具有挑戰(zhàn)性。
    您可以使用以下命令來(lái)生成單文件應(yīng)用程序。

    l 依賴框架的單文件APP:

    n DotNet PUBLISH-r Linux-x64--自含式FALSE/p:PublishSingleFile=TRUE。

    l 自含式單文件APP:

    n DotNet PUBLISH-r Linux-x64--自含式TRUE/p:PublishSingleFile=TRUE

    您還可以使用項(xiàng)目文件配置單個(gè)文件發(fā)布。

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    <Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>

    <OutputType>Exe</OutputType>

    <TargetFramework>net5.0</TargetFramework>

    <!-- The OS and CPU type you are targeting -->

    <RuntimeIdentifier>linux-x64</RuntimeIdentifier>

    <!-- Determine self-contained or framework-dependent -->

    <SelfContained>true</SelfContained>

    <!-- Enable single file -->

    <PublishSingleFile>true</PublishSingleFile>

    </PropertyGroup>

    </Project>

    您可以嘗試使用程序集修剪來(lái)減小應(yīng)用程序的大小。它可能會(huì)通過(guò)過(guò)度修剪來(lái)破壞應(yīng)用程序,因此建議在使用此功能后徹底測(cè)試您的應(yīng)用程序。程序集調(diào)整還會(huì)移除提前編譯的讀到運(yùn)行本機(jī)代碼(用于被調(diào)整的程序集),這主要是為了提高性能。您需要在裁剪之后測(cè)試應(yīng)用程序的性能。通過(guò)使用PublishReadyToRun屬性(并設(shè)置為true),您可以在裁剪后即可運(yùn)行編譯您的應(yīng)用程序。
    注:

    • l 應(yīng)用程序是特定于操作系統(tǒng)和架構(gòu)的。您需要發(fā)布每種配置(Linuxx64、LinuxArm64、Windowsx64、…)。。
    • l 配置文件(如*.runtimeconfig.json)包含在單個(gè)文件中。如果需要,您可以在單個(gè)文件旁邊放置額外的配置文件(可能是為了測(cè)試)。
    • l 默認(rèn)情況下,單個(gè)文件中不包括.pdb文件。您可以使用<DebugType>Embed</DebugType>屬性啟用PDB嵌入。
    • l IncludeNativeLibrariesForSelfExtract屬性可用于在Windows和MacOS上嵌入本機(jī)運(yùn)行時(shí)二進(jìn)制文件,但它們必須在運(yùn)行時(shí)解壓縮到臨時(shí)存儲(chǔ)中。不建議在一般情況下使用此功能。

    ClickOnce

    多年來(lái),ClickOnce一直是流行的.NET部署選項(xiàng)。現(xiàn)在,它被.NET Core 3.1和.NET5.0 Windows應(yīng)用程序支持。當(dāng)我們將Windows窗體和WPF支持添加到.NET Core 3.0中時(shí),我們知道很多人會(huì)希望使用ClickOnce進(jìn)行應(yīng)用程序部署。在過(guò)去的一年里,.NET和Visual Studio團(tuán)隊(duì)共同努力,在命令行和Visual Studio中啟用ClickOnce發(fā)布。
    從項(xiàng)目一開(kāi)始,我們就有兩個(gè)目標(biāo):

    • l 在Visual Studio中為ClickOnce啟用熟悉的體驗(yàn)。
    • l 使用MSBuild或MAGE工具,通過(guò)命令行流為ClickOnce發(fā)布啟用現(xiàn)代CI/CD。
    • 用圖片向你展示這種體驗(yàn)是最容易的。


    讓我們從Visual Studio體驗(yàn)開(kāi)始,它以項(xiàng)目發(fā)布為中心。


    我們目前支持的主要部署模式是依賴于框架的應(yīng)用程序。很容易依賴于.NET桌面運(yùn)行時(shí)(即包含WPF和Windows窗體的桌面運(yùn)行時(shí))。如果需要,ClickOnce安裝程序?qū)⒃谟脩粲?jì)算機(jī)上安裝.NET運(yùn)行時(shí)。我們還打算支持獨(dú)立和單一文件應(yīng)用程序。


    您可能會(huì)想,您是否仍然能夠利用ClickOnce脫機(jī)和更新功能。可以,停那兒吧。


    MAGE最大的變化是它現(xiàn)在是一個(gè).NET工具,發(fā)布在NuGet上。這意味著你不需要在你的機(jī)器上安裝任何特殊的東西。您只需要.NET5.0SDK,然后就可以將MAGE安裝為一個(gè).NET工具。您也可以使用它發(fā)布.NET Framework應(yīng)用程序,但是,SHA1簽名和部分信任支持已被移除。
    MAGE安裝命令如下:

    dotnet tool install -g Microsoft.DotNet.Mage

    在您制作并分發(fā)了ClickOnce安裝程序之后,您的用戶將看到熟悉的ClickOnce安裝對(duì)話框。


    當(dāng)您使更新可用時(shí),您的用戶將看到更新對(duì)話框。


    最后總結(jié)

    Net 5.0是另一個(gè)大版本,它應(yīng)該會(huì)改進(jìn)你使用.NET的許多方面。我們已經(jīng)實(shí)現(xiàn)了一系列的改進(jìn),從單文件應(yīng)用程序到性能,從Json序列化的可用性到ARM64的支持。雖然今天可能是您使用.NET5.0的第一天,但我們?cè)谖④浀漠a(chǎn)品中運(yùn)行.NET5.0已經(jīng)有幾個(gè)月了。我們相信,它已準(zhǔn)備好供您使用、運(yùn)營(yíng)您的業(yè)務(wù)并為您的應(yīng)用程序提供動(dòng)力。C#9和F#5中的新語(yǔ)言改進(jìn)應(yīng)該會(huì)使您的代碼更具表現(xiàn)力,更易于編寫(xiě)。對(duì)于您現(xiàn)有的應(yīng)用程序來(lái)說(shuō),.Net 5.0也是一個(gè)很好的選擇。在許多情況下,您可以毫不費(fèi)力地升級(jí)。
    如果您對(duì)性能感興趣,您可能會(huì)對(duì)我們?cè)赥echEmpower基準(zhǔn)測(cè)試方面的進(jìn)展感興趣。回過(guò)頭來(lái)看,您可以看到.NETCore3.1在最新一輪第19輪中的表現(xiàn)相當(dāng)不錯(cuò)。我們期待著在即將到來(lái)的第20輪中看到.NET5.0。當(dāng)?shù)?0輪最終確定并發(fā)布時(shí),新的排名將是值得關(guān)注的。
    在.NET5.0中的改進(jìn)是許多人共同努力的結(jié)果,他們?cè)贕itHub上,在世界各地,在多個(gè)時(shí)區(qū)協(xié)同工作。感謝為這一版本做出貢獻(xiàn)的每一個(gè)人。別擔(dān)心,有很多機(jī)會(huì)可以貢獻(xiàn)自己的力量。NET5.0版本已經(jīng)結(jié)束,但是下一個(gè)版本已經(jīng)開(kāi)始了。

    Net 5.0是另一個(gè)大版本,它應(yīng)該會(huì)改進(jìn)你使用.NET的許多方面。我們已經(jīng)實(shí)現(xiàn)了一系列的改進(jìn),從單文件應(yīng)用程序到性能,從Json序列化的可用性到ARM64的支持。雖然今天可能是您使用.NET5.0的第一天,但我們?cè)谖④浀漠a(chǎn)品中運(yùn)行.NET5.0已經(jīng)有幾個(gè)月了。我們相信,它已準(zhǔn)備好供您使用、運(yùn)營(yíng)您的業(yè)務(wù)并為您的應(yīng)用程序提供動(dòng)力。C#9和F#5中的新語(yǔ)言改進(jìn)應(yīng)該會(huì)使您的代碼更具表現(xiàn)力,更易于編寫(xiě)。對(duì)于您現(xiàn)有的應(yīng)用程序來(lái)說(shuō),.Net 5.0也是一個(gè)很好的選擇。在許多情況下,您可以毫不費(fèi)力地升級(jí)。
    如果您對(duì)性能感興趣,您可能會(huì)對(duì)我們?cè)赥echEmpower基準(zhǔn)測(cè)試方面的進(jìn)展感興趣。回過(guò)頭來(lái)看,您可以看到.NETCore3.1在最新一輪第19輪中的表現(xiàn)相當(dāng)不錯(cuò)。我們期待著在即將到來(lái)的第20輪中看到.NET5.0。當(dāng)?shù)?0輪最終確定并發(fā)布時(shí),新的排名將是值得關(guān)注的。
    在.NET5.0中的改進(jìn)是許多人共同努力的結(jié)果,他們?cè)贕itHub上,在世界各地,在多個(gè)時(shí)區(qū)協(xié)同工作。感謝為這一版本做出貢獻(xiàn)的每一個(gè)人。別擔(dān)心,有很多機(jī)會(huì)可以貢獻(xiàn)自己的力量。NET5.0版本已經(jīng)結(jié)束,但是下一個(gè)版本已經(jīng)開(kāi)始了。



    原文地址:https://www.cnblogs.com/powertoolsteam/p/dotnet5.html

網(wǎng)站首頁(yè)   |    關(guān)于我們   |    公司新聞   |    產(chǎn)品方案   |    用戶案例   |    售后服務(wù)   |    合作伙伴   |    人才招聘   |   

友情鏈接: 餐飲加盟

地址:北京市海淀區(qū)    電話:010-     郵箱:@126.com

備案號(hào):冀ICP備2024067069號(hào)-3 北京科技有限公司版權(quán)所有