首頁 > 科技

NET 6 Preview 4 已釋出,這些新功能值得關注!

2021-06-01 23:54:21

作者 | WeihanLi 責編 | 歐陽姝黎

出品 | amazingdotnet

我們很高興地釋出 .NET 6 Preview 4。現在,我們到 .NET 6 正式釋出尚有一半。現在是再次瀏覽.NET 6 全部內容的好時機,就像第一篇預覽文章一樣。許多功能處於最終形式,而其他功能也將很快釋出,因為已經為釋出提供了基礎構建塊。Preview 4 為在 11月交付最終的 .NET 6 版本奠定了堅實的基礎,並提供了完整的功能和體驗。如果您尚未在環境中嘗試過.NET 6,它也已準備好進行實際測試。

說到最終版本,我們現在有個會議!為 .NET Conf 2021預訂11月9日至11日。我們將在9日釋出.NET 6,其中將進行許多深入的演講和演示,向您介紹有關 .NET 6 的所有知識。

您可以下載適用於Linux,macOS和Windows的 .NET 6 Preview 4。

  • 安裝程式和二進位制檔案
  • 容器映象
  • Linux軟體包
  • 釋出說明
  • 已知的問題
  • GitHub問題追蹤

有關 Web和資料訪問方案的新增功能,請參閱ASP.NET Core和EF Core帖子以獲取更多詳細資訊。還有一個新的 .NET MAUI 帖子,描述了新的客戶端應用程式體驗,以及一個 Hot reload 帖子,描述了開發人員生產力的新方法。

.NET 6 已通過 Visual Studio 16.11 和Visual Studio for Mac 8.9進行了測試。如果您想在Visual Studio嘗試.NET 6,我們建議您使用這些版本。

BUILD 2021

微軟BUILD大會就在這個星期。它是免費的,並且可以在網路上觀看直播。現在註冊還為時不晚。

您一定想要了解這些介紹,其中包括有關.NET 6的大量討論和演示,這些演示向您展示了新功能和現在的可能。

  • .NET進行現代應用程式開發的未來
  • .NET 6深入探討;有什麼新東西,還將有哪些新東西
  • .NET團隊 「專家提問」

.NET 6 主題

我們從2020年末開始在GitHub上規劃.NET 6。我們在廣泛的主題中確定了八個主題,包括行業方案,支援和教育。主題佔我們釋出工作的一半到四分之三。有許多項目沒有達到主題的水平或意義重大但沒有主題意義的項目(例如支援Apple Silicon裝置)。

以下是.NET 6主題,每個主題都有一個句子摘要。它們以與顯示在themesof.net中相同的順序列出。

  • .NET吸引新的開發人員和學生-通過清晰的文件,更簡單的程式碼模型(需要學習的檔案和概念更少)以及為測試和生產環境部署的方式,在Visual Studio產品中提供非常簡單的體驗。
  • .NET具有出色的客戶端應用程式開發體驗-提供了一個跨平臺的客戶端應用程式基礎,可以無縫地迎合桌面,移動和 Web開發人員,並可以在 Blazor 和 Xamarin 等現有應用程式類型的基礎上進行擴展。
  • .NET被認為是構建雲原生應用程式的引人注目的框架-提供主要針對性能和可觀察性的基本雲原生功能,改進與雲原生和容器生態系統的整合以及演示了很多內容的雲原生元件(yarp),它通過重要的雲使用用例展示了 .NET 很大的價值。
  • 企業和LTS-為將.NET與重要的應用程式結合使用提供更簡單,更可預測的應用模型,並更好地滿足大型企業和政府客戶的需求。
  • 通過提高質量,信心和支援來發展 .NET 生態系統—建立長期的社群協作,旨在將社群開發人員的水平提升到與 Microsoft 類似的水平,並(反過來)提供新功能和新體驗使得企業開發人員更容易依賴社群開放原始碼項目中的庫,這些庫不一定與大公司有關聯或由大公司支援。
  • 改善.NET開發人員的 inner-loop 效能-改善開發人員的工作效率,包括提高構建效能,熱重啟和熱過載。
  • 使用運行時執行資訊(PGO)改善啟動和吞吐量—提供一種新模型來基於可用於更快啟動,更高吞吐量和更小的二進位制檔案的運行時資訊提高效能。
  • 滿足開發人員的期望-根據反饋在整個.NET產品中進行改進,並啟用具有現有功能的新方案。

以下帖子將更詳細地討論其中一些主題:

  • .NET 6預覽版1
  • .NET 6預覽版2
  • 關於 PGO 的對話

統一 .NET 平臺

在過去的帖子和會議上,我們已經討論了很多有關.NET統一的話題,但是主題中卻缺少它。平臺統一已融入到我們所做的所有事情中,並且不需要自己的主題。可以將其視為超出所列主題之外的一個大型主題。它貫穿多個主題,是團隊前進的基本假設。

Inner-loop 效能項目是一個很好的例子。假定.NET 6應用程式都共享相同的基礎設施,例如使用相同的構建系統和庫。在存在技術差異的地方,如使用不同的運行時(CoreCLR 或 Mono)或程式碼生成技術(AOT或JIT),我們將這些因素考慮在內並提供務實且適當的體驗,並且偏向於幾乎不可察覺的體驗差異。EventPipe項目就是另一個類似的例子。

生產信心

我們將很快開始釋出在生產中受支援的「上線」版本。我們目前正為此目標。我們的開發模型圍繞實現生產工作負載而進行,即使我們正在完成上述所有主題的工作。

生產信心始於 dotnet.microsoft.com 網站。從 Preview 1 開始,它已經在 .NET 6 上運行了一半的站點負載。雖然規模不大,但對於我們的團隊來說,這是一個重要的站點,我們非常重視它。.NET 6一直像冠軍一樣為我們工作。

我們還與微軟使用.NET預覽版部署其生產應用程式團隊合作。他們這樣做是為了儘早使用新的 .NET 功能。這些團隊一直在尋找減少其雲託管成本的機會,事實證明,部署新的.NET版本是最有效,最省力的方法之一。這些團隊為我們提供了早期反饋,可幫助我們確保新功能可用於全球生產。由於它們是我們的第一批生產使用者,因此它們也極大地影響最終特性的面貌。

所有這些對現實應用程式的早期測試都建立了我們對.NET 6將為運行您的應用程式做好準備的信心。

文章的其餘部分專門介紹預覽版4中的新增功能。

工具:使用Visual Studio偵錯程式和dotnetCLI進行熱重灌

Hot Reload是一種新體驗,使您可以在運行時對應用程式的原始碼進行編輯,而無需手動暫停應用程式或遇到斷點。Hot Reload通過減少重新啟動正在運行的應用程式所需的次數來提高開發人員的效率。

在此版本中,熱重載入可用於許多類型的應用程式,例如WPF,Windows窗體,WinUI,ASP.NET,控制檯應用程式以及在CoreCLR運行時之上運行的其他框架。我們也正在努力將該技術引入在Mono之上運行的WebAssembly,iOS和Android應用程式中,但這種技術仍將繼續開發(在以後的Preview中)。

若要開始測試此功能,請安裝Visual Studio 2019版本16.11 Preview 1,然後使用Visual Studio偵錯程式(F5)啟動您的應用程式。應用程式運行後,您現在可以使用新選項進行程式碼更改,並使用新的「應用程式碼更改」按鈕應用程式碼,如下所示。

也可以通過該dotnet watch工具進行熱重灌。預覽版4提供了很多修復可以改善這種體驗。

如果您想了解有關熱過載的更多資訊,請閱讀.NET熱過載簡介。

System.Text.Json 對IAsyncEnumerable的支援

IAsyncEnumerable<T>是.NET Core 3.0和C#8中新增的一項重要功能。使用IAsyncEnumerable<T> 實現了對 System.Text.Json的(反)序列化新的增強功能。

以下示例將流用作任何非同步資料來源的示例。資料來源可以是本地計算機上的檔案,也可以是資料庫查詢或Web服務API呼叫的結果。

流序列化

如下面的示例所示,System.Text.Json現在支援將IAsyncEnumerable<T>值序列化為JSON陣列。

using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;

static async IAsyncEnumerable<int> PrintNumbers(int n)
{
for (int i = 0; i < n; i++) yield return i;
}

using Stream stream = Console.OpenStandardOutput();
var data = new { Data = PrintNumbers(3) };
await JsonSerializer.SerializeAsync(stream, data); // prints {"Data":[0,1,2]}

IAsyncEnumerable 值僅支援使用非同步序列化方法處理。嘗試使用同步方法進行序列化將導致 NotSupportedException 拋出異常。

流式反序列化

流式反序列化需要返回 IAsyncEnumerable<T> 的新 API 。我們為此添加了 JsonSerializer.DeserializeAsyncEnumerable 方法,如下面的示例所示。

using System;
using System.IO;
using System.Text;
using System.Text.Json;

var stream = new MemoryStream(Encoding.UTF8.GetBytes("[0,1,2,3,4]"));
await foreach (int item in JsonSerializer.DeserializeAsyncEnumerable<int>(stream))
{
Console.WriteLine(item);
}

此示例將按需反序列化元素,並且在使用特別大的資料流時可能很有用。它僅支援從根級JSON陣列讀取,儘管將來可以根據反饋放寬對它的讀取。

現有的 DeserializeAsync方法名義上支援IAsyncEnumerable<T>,但在其非流式方法簽名的範圍內,它必須以單個值返回最終結果。如以下示例所示。

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.Json;

var stream = new MemoryStream(Encoding.UTF8.GetBytes(@"{""Data"":[0,1,2,3,4]}"));
var result = await JsonSerializer.DeserializeAsync<MyPoco>(stream);
await foreach (int item in result.Data)
{
Console.WriteLine(item);
}

public class MyPoco
{
public IAsyncEnumerable<int> Data { get; set; }
}

在此示例中,反序列化程式將IAsyncEnumerable在返回反序列化物件之前將所有內容緩衝在記憶體中。這是因為解析器在返回結果之前需要讀取整個JSON。

System.Text.Json:可寫DOM功能

在寫JSON DOM功能增加了一個新的簡單和高效能的程式設計模型。這種新的API具有吸引力,因為它避免了序列化的複雜性和儀式以及DOM的傳統成本。System.Text.Json

這個新的API具有以下優點:

  • 在無法或不希望使用POCO類型的情況下,或者在JSON模式不固定且必須進行檢查的情況下,可以使用輕型替代序列化。
  • 啟用對大樹子集的有效修改。例如,可以有效地導航到大JSON樹的子部分,並從該子部分讀取陣列或反序列化POCO。LINQ也可以與此一起使用。
  • 啟用使用C#dynamic關鍵字,該關鍵字允許使用鬆散類型的,更類似於指令碼的模型。

我們正在尋找有關對支援dynamic的反饋。如果dynamic支援對您很重要,請給我們您的反饋。

更多詳細資訊,請訪問dotnet / runtime#6098。

可寫的DOM API

可寫DOM公開了以下類型。

namespace System.Text.Json.Node
{
public abstract class JsonNode {...};
public sealed class JsonObject : JsonNode, IDictionary<string, JsonNode?> {...}
public sealed class JsonArray : JsonNode, IList<JsonNode?> {...};
public abstract class JsonValue : JsonNode {...};
}

示例程式碼

下面的示例演示了新的程式設計模型。

    // Parse a JSON object
JsonNode jNode = JsonNode.Parse("{"MyProperty":42}");
int value = (int)jNode["MyProperty"];
Debug.Assert(value == 42);
// or
value = jNode["MyProperty"].GetValue<int>();
Debug.Assert(value == 42);

// Parse a JSON array
jNode = JsonNode.Parse("[10,11,12]");
value = (int)jNode[1];
Debug.Assert(value == 11);
// or
value = jNode[1].GetValue<int>();
Debug.Assert(value == 11);

// Create a new JsonObject using object initializers and array params
var jObject = new JsonObject
{
["MyChildObject"] = new JsonObject
{
["MyProperty"] = "Hello",
["MyArray"] = new JsonArray(10, 11, 12)
}
};

// Obtain the JSON from the new JsonObject
string json = jObject.ToJsonString();
Console.WriteLine(json); // {"MyChildObject":{"MyProperty":"Hello","MyArray":[10,11,12]}}

// Indexers for property names and array elements are supported and can be chained
Debug.Assert(jObject["MyChildObject"]["MyArray"][1].GetValue<int>() == 11);

Microsoft.Extensions.Logging編譯時原始碼生成器

.NET 6引入了這種LoggerMessageAttribute類型。此屬性是名稱空間Microsoft.Extensions.Logging的一部分,使用時,它會生成效能記錄API的原始碼。原始碼日誌支援旨在為現代.NET應用程式提供高度可用和高效能的日誌記錄解決方案。自動生成的原始碼依賴於ILogger介面和LoggerMessage.Define功能。

當LoggerMessageAttribute用於partial日誌記錄方法時,將觸發原始碼生成器。觸發後,它既可以自動生成partial其修飾方法的實現,也可以生成帶有有關正確用法提示的編譯時診斷。編譯時日誌記錄解決方案在運行時通常比現有的日誌記錄方法快得多。它通過消除裝箱,臨時分配和副本來最大程度地實現了這一目標。

與直接手動使用 LoggerMessage.Define API相比,有很多好處:

  • 語法更短,更簡單:聲明性屬性的使用而不是進行模板式編碼。
  • 指導開發人員的體驗:生成器會給出警告,以幫助開發人員做正確的事。
  • 支援任意數量的日誌記錄參數。LoggerMessage.Define最多支援六個。
  • 支援動態日誌級別。這單靠LoggerMessage.Define是不可能的。

如果您想跟蹤改進和已知問題,請參閱dotnet / runtime#52549。

基本用法

要使用LoggerMessageAttribute,需要使用的類和方法partial。程式碼生成器在編譯時觸發,並生成該partial方法的實現。

public static partial class Log
{
[LoggerMessage(EventId = 0, Level = LogLevel.Critical, Message = "Could not open socket to `{hostName}`")]
public static partial void CouldNotOpenSocket(ILogger logger, string hostName);
}

在前面的示例中,日誌記錄方法為static,並且日誌級別在屬性定義中指定。在靜態上下文中使用屬性時,必須將ILogger例項作為參數。您也可以選擇在非靜態上下文中使用該屬性。有關更多示例和使用場景,請訪問有關編譯時日誌記錄源生成器的文件。

System.Linq增強

已新增新的System.LINQ API,這些API已由社群提出請求並做出了貢獻。

Enumerable 對Index和Range參數的支援

該方法現在從可列舉的末尾接受索引,如下面的示例所示。Enumerable.ElementAt

Enumerable.Range(1, 10).ElementAt(^2); // returns 9

已新增一個接受參數的過載。它簡化了可列舉序列的切片:Enumerable.Take``Range

  • source.Take(..3) 代替 source.Take(3)
  • source.Take(3..) 代替 source.Skip(3)
  • source.Take(2..7) 代替 source.Take(7).Skip(2)
  • source.Take(^3..) 代替 source.TakeLast(3)
  • source.Take(..^3) 代替 source.SkipLast(3)
  • source.Take(^7..^3)代替。source.TakeLast(7).SkipLast(3)

感謝@dixin對此的貢獻。

TryGetNonEnumeratedCount

該TryGetNonEnumeratedCount方法嘗試在不強制列舉的情況下獲取可列舉的源的計數。如下面的示例所示,這種方法在需要在列舉之前預先分配緩衝區的場景中很有用。

List<T> buffer = source.TryGetNonEnumeratedCount(out int count) ? new List<T>(capacity: count) : new List<T>();
foreach (T item in source)
{
buffer.Add(item);
}

TryGetNonEnumeratedCount 檢查原始碼是否實現ICollection/ICollection<T> 或利用Linq所採用的一些內部優化。

DistinctBy/ UnionBy/ IntersectBy/ExceptBy

如下面的示例所示,已將新的變體新增到集合操作中,這些變體允許使用通過鍵選擇器函數指定相等性。

Enumerable.Range(1, 20).DistinctBy(x => x % 3); // {1, 2, 3}

var first = new (string Name, int Age)[] { ("Francis", 20), ("Lindsey", 30), ("Ashley", 40) };
var second = new (string Name, int Age)[] { ("Claire", 30), ("Pat", 30), ("Drew", 33) };
first.UnionBy(second, person => person.Age); // { ("Francis", 20), ("Lindsey", 30), ("Ashley", 40), ("Drew", 33) }

MaxBy/MinBy

MaxBy和MinBy方法允許使用鍵選擇器查詢最大或最小元素,如以下示例所示。

var people = new (string Name, int Age)[] { ("Francis", 20), ("Lindsey", 30), ("Ashley", 40) };
people.MaxBy(person => person.Age); // ("Ashley", 40)

Chunk

Chunk 用於將可列舉的源分塊為固定大小的切片,如以下示例所示。

IEnumerable<int[]> chunks = Enumerable.Range(0, 10).Chunk(size: 3); // { {0,1,2}, {3,4,5}, {6,7,8}, {9} }

感謝Robert Andersson對此實現的貢獻。

FirstOrDefault/ LastOrDefault/SingleOrDefault過載採取預設參數

現有FirstOrDefault/ LastOrDefault/SingleOrDefault方法如果源列舉是空的返回default(T)。如您在以下示例中看到的那樣,添加了新的過載,該過載接受在這種情況下要返回的預設參數。

Enumerable.Empty<int>().SingleOrDefault(-1); // returns -1

感謝@ Foxtrek64對此實現的貢獻。

Zip 接受三個列舉過載

該方法現在支援組合三個列舉介面,你可以在下面的例子中看到。

var xs = Enumerable.Range(1, 10);
var ys = xs.Select(x => x.ToString());
var zs = xs.Select(x => x % 2 == 0);

foreach ((int x, string y, bool z) in Enumerable.Zip(xs,ys,zs))
{
}

感謝Huo Yaoyuan對此實現的貢獻。

大大提高了Windows上的FileStream效能

FileStream 已在.NET 6中重新編寫,以在Windows上具有更高的效能和可靠性。

在重新編寫項目已逐步在五個大PR:

  • 引入FileStreamStrategy作為FileStream重寫的第一步
  • FileStream重寫第二部分
  • FileStream優化
  • FileStream重寫:使用IValueTaskSource代替TaskCompletionSource
  • FileStream重寫:在AsyncWindowsFileStreamStrategy中快取ValueTaskSource

最終結果是FileStream在Windows上為非同步IO創建時永不阻塞。這是一個重大改進。您可以在基準測試中觀察到這一點,我們將在稍後進行介紹。

配置

第一個PR支援FileStream在運行時選擇實現。此模式最明顯的好處是可以切換回舊的.NET 5實施,您可以在runtimeconfig.json中使用以下設定進行操作。

{
"configProperties": {
"System.IO.UseNet5CompatFileStream": true
}
}

我們計劃接下來新增一個io_uring策略,該策略利用在最近的lINUX核心中同名的功能。

效能基準

讓我們使用BenchmarkDotNet來衡量改進。

public class FileStreamPerf
{
private const int FileSize = 1_000_000; // 1 MB
private Memory<byte> _buffer = new byte[8_000]; // 8 kB

[GlobalSetup(Target = nameof(ReadAsync))]
public void SetupRead() => File.WriteAllBytes("file.txt", new byte[FileSize]);

[Benchmark]
public async ValueTask ReadAsync()
{
using FileStream fileStream = new FileStream("file.txt", FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 4096, useAsync: true);
while (await fileStream.ReadAsync(_buffer) > 0)
{
}
}

[Benchmark]
public async ValueTask WriteAsync()
{
using FileStream fileStream = new FileStream("file.txt", FileMode.Create, FileAccess.Write, FileShare.Read, bufferSize: 4096, useAsync: true);
for (int i = 0; i < FileSize / _buffer.Length; i++)
{
await fileStream.WriteAsync(_buffer);
}
}

[GlobalCleanup]
public void Cleanup() => File.Delete("file.txt");
}

```ini
BenchmarkDotNet=v0.13.0, OS=Windows 10.0.18363.1500 (1909/November2019Update/19H2)
Intel Xeon CPU E5-1650 v4 3.60GHz, 1 CPU, 12 logical and 6 physical cores
.NET SDK=6.0.100-preview.5.21267.9
[Host] : .NET 5.0.6 (5.0.621.22011), X64 RyuJIT
Job-OIMCTV : .NET 5.0.6 (5.0.621.22011), X64 RyuJIT
Job-CHFNUY : .NET 6.0.0 (6.0.21.26311), X64 RyuJIT

**環境:**具有啟用了BitLocker的SSD驅動器的Windows 10

結果:

  • 現在,讀取1 MB檔案的速度提高了2倍,而寫入速度則提高了4倍。
  • 記憶體分配從39 KB減少到1 KB!這是97.5%的改善!

這些更改將為FileStreamWindows使用者提供顯著的改進。更多詳細資訊,請訪問dotnet / core#6098。

增強的日期,時間和時區支援

迄今為止,與日期和時間相關的類型已進行了以下改進。

新的DateOnly和TimeOnly結構

添加了僅日期和時間結構,具有以下特徵:

  • 每個代表的一個DateTime的一半,要麼僅是日期部分,要麼僅是時間部分。
  • DateOnly是日期,週年紀念日和工作日的理想選擇。它與SQL Server的date類型一致。
  • TimeOnly是定期會議,鬧鐘和每週工作時間的理想選擇。它與SQL Server的time類型一致。
  • 補充了現有的日期/時間類型(DateTime,DateTimeOffset,TimeSpan,TimeZoneInfo)。
  • 在System名稱空間中,與現有的相關類型一樣,在CoreLib中提供。

效能改進 DateTime.UtcNow

此改進具有以下好處:

  • 修復了2.5倍的效能迴歸,以獲取Windows上的系統時間。
  • 利用5分鐘的Windows滑動快取跳過第二個資料,而不是每次呼叫都提取資料。

在所有平臺上均支援Windows和IANA時區

此改進具有以下優點:

  • 使用時的隱式轉換(https://github.com/dotnet/runtime/pull/49412)TimeZoneInfo.FindSystemTimeZoneById
  • 通過新的API顯式轉換上TimeZoneInfo:TryConvertIanaIdToWindowsId,TryConvertWindowsIdToIanaId,和HasIanaId(https://github.com/dotnet/runtime/issues/49407)
  • 改進跨平臺的支援和使用不同時區類型的系統之間的互操作。
  • 無需使用TimeZoneConverter 開源庫。該功能現已內建。

改進的時區顯示名稱

此改進具有以下好處:

  • 從TimeZoneInfo.GetSystemTimeZones中返回的列表中的顯示名稱中消除歧義。
  • 利用ICU / CLDR全球化資料。
  • 僅限Unix。Windows仍使用登錄檔資料。以後可能會更改。

其他

  • UTC時區的顯示名稱和標準名稱已硬編碼為英語,並且現在使用與其餘時區資料相同的語言(CurrentUICulture在Unix上,在Windows為OS預設語言)。
  • 由於大小限制,WASM中的時區顯示名稱改用非本地化的IANA ID。
  • TimeZoneInfo.AdjustmentRule巢狀類將其BaseUtcOffsetDelta內部屬性公開,並獲取一個新的建構函式baseUtcOffsetDelta作為參數。(https://github.com/dotnet/runtime/issues/50256)
  • TimeZoneInfo.AdjustmentRule 還獲得了在Unix(https://github.com/dotnet/runtime/pull/49733)上載入時區的多項修復程式(https://github.com/dotnet/runtime/pull/50131)

CodeGen

RyuJIT編譯器進行了以下改進。

社群貢獻

在過去幾個月中,@ SingleAccretion一直在忙於以下改進。這是對.NET 6 Preview 3的補充。謝謝!

  • dotnet / runtime#50373 —如果樹是CSE候選者,不要棄用雙重否定
  • dotnet / runtime#50450 —處理通過幫助程式進行的強制轉換並在值編號中摺疊溢位操作
  • dotnet / runtime#50702 —刪除了GS Cookies的必須初始化的要求
  • dotnet / runtime#50703 —不要混淆fgMorphBlocks中的fgDispBasicBlocks

動態PGO

為了支援動態PGO,進行了以下改進。

  • dotnet / runtime#51664 —更新JIT以使用從交叉基因處理的PGO資料中看到的新「 LikelyClass」記錄
  • dotnet / runtime#50213 —更好地容忍邊緣輪廓不一致
  • dotnet / runtime#50633 —修復了混合的PGO / nonPGO編譯
  • dotnet / runtime#50765 —修改fgExpandRunRarelyBlocks
  • dotnet / runtime#51593 —修改內聯刻度計算

JIT迴圈優化

對迴圈優化進行了以下改進。

  • dotnet / runtime#50982 —概括迴圈反演
  • dotnet / runtime#51757 —不要在迴圈克隆期間重新計算preds列表

LSRA

對線性掃描寄存器分配(LRSA)進行了以下改進。

  • dotnet / runtime#51281 —改進LRSA統計資訊以包括寄存器選擇啟發式資訊

最佳化

  • dotnet / runtime#49930 —在值編號級別摺疊空檢查const字元串
  • dotnet / runtime#50000 —對引用類型的初始化的靜態只讀欄位進行摺疊空檢查
  • dotnet / runtime#50112 —不要在潛在的BBJ_THROW候選物件中分配字元串文字
  • dotnet / runtime#50644 —為VectorX啟用CSE。
  • dotnet / runtime#50806 —如果後面沒有意外阻止,請放棄尾部呼叫
  • dotnet / runtime#50832 —更新Vector<T>以支援nint和修改nuint
  • dotnet / runtime#51409-概括圍繞分支空流程的優化

.NET診斷:用於Mono的EventPipe和改進的EventPipe效能

EventPipe是.NET的跨平臺機制,用於輸出事件,效能資料和計數器。

從.NET 6開始,我們將實現從C ++移到了C。通過這一更改,Mono也將能夠使用EventPipe!這意味著CoreCLR和Mono將使用相同的事件基礎結構,包括.NET Diagnostics CLI工具!此更改還使CoreCLR的尺寸有所減小:

我們還進行了一些更改,以提升高負載下的EventPipe吞吐量。在最初的幾個預覽中,我們進行了一系列更改,使吞吐量提高了.NET 5所能達到的2.06倍

使用 dotnet/diagnostics 中 EventPipeStress 框架收集的資料。應用程式以最快的速度寫入事件,持續60秒。記錄了成功和刪除事件的數量。

有關更多資訊,請參見dotnet / runtime#45518。

IL Trimming

預設情況下啟用警告

修剪警告會告訴您修剪可能會刪除運行時使用的程式碼的地方。以前預設情況下會禁用這些警告,因為這些警告非常嘈雜,這在很大程度上是由於.NET平臺未作為一流方案參與修剪。

我們已經為.NET庫的大部分(運行時庫,而不是ASP.NET Core或Windows Desktop框架)添加了註解,以便它們產生準確的修剪警告。因此我們認為是時候預設啟用修整警告了。

您可以通過將設定<SuppressTrimAnalysisWarnings>為來禁用警告true。在早期版本中,您可以設定相同的屬性為false以檢視修剪警告。

修剪警告為修剪過程帶來了可預測性,並增強了開發人員的控制能力。我們將繼續在以後的版本中註解更多的 .NET 庫,包括 ASP.NET Core。我們希望社群也將通過註解更多程式碼以保護修剪安全,從而改善修剪生態系統。

更多資訊:

  • .NET 6中的修剪警告
  • 準備用於修剪的.NET庫

預設TrimMode=link

.NET 6中新的預設修剪模式為link。link TrimMode可以通過修剪不僅未使用的程式集還有不用的成員來顯著的修剪效果。

在.NET 5中,修剪預設情況下嘗試查詢和刪除未引用的程式集。這樣比較安全,但收益有限。現在預設情況下,修剪警告處於開啟狀態,開發人員可以對修剪的結果充滿信心。

讓我們來看一下通過修整.NET SDK工具之一進行的修整改進。我將使用crossgen,Ready To Run 編譯器。Crossgen團隊能夠解決的問題僅需修剪一些警告即可進行修剪。

首先,讓我們看一下如何將Crossgen釋出為一個自包含的應用程式,而無需進行修整。它是80 MB(包括.NET運行時和所有庫)。

然後,我們可以嘗試使用(現在是舊版的).NET 5預設修剪模式copyused。結果下降到55 MB。

新的.NET 6預設修剪模式link將自包含檔案的大小進一步減小到36MB。

我們希望新的link修整模式能更好地滿足修整的期望:節省大量成本並獲得可預測的結果。

與NativeAOT共享的模型

我們還為Native AOT實驗實施了相同的修剪警告,這將以幾乎相同的方式改善Native AOT編譯體驗。

單檔案釋出

對單檔案應用程式釋出進行了以下改進。

靜態分析

.NET 5中添加了用於單檔案釋出的分析器,以警告Assembly.Location 和其他一些在單檔案包中表現不同的API。

對於.NET 6 Preview 4,我們改進了分析以允許自定義警告。如果您有在單檔案釋出中不起作用的API,則可以使用屬性將其標記[RequiresAssemblyFiles],如果啟用了分析器,則會出現警告。新增該屬性還將使方法中與單個檔案相關的所有警告均消除,因此您可以使用該警告將警告向上傳播到公共API。

PublishSingleFile設定為true時,會為exe項目自動啟用分析器,但也可以通過設定EnableSingleFileAnalysis為true來為任何項目啟用分析器。如果要將庫嵌入單個檔案包中,這可能會有所幫助。

壓縮

現在單檔案包支援壓縮,這可以通過設定屬性EnableCompressionInSingleFile到true來啟用。在運行時,根據需要將檔案解壓縮到記憶體中。在某些情況下,壓縮可以節省大量空間。

讓我們看一下NuGet Package Explorer一起使用的壓縮和不壓縮的單個檔案釋出。

不壓縮:172 MB

壓縮後:71.6 MB

壓縮會大大增加應用程式的啟動時間,尤其是在Unix平臺上(因為它們具有無法與壓縮一起使用的無副本快速啟動路徑)。啟用壓縮後,應該測試您的應用程式,以檢視是否可以接受額外的啟動成本。

PublishReadyToRun 現在預設使用crossgen2

預設情況下,釋出 ReadyToRun 時會啟用 Crossgen2。它還可選地支援生成組合配置。

公開了以下設定,使您可以配置釋出並準備運行程式碼。下面的設定被設定為其預設值。

    <PublishReadyToRun>false</PublishReadyToRun>
<!-- set to true to enable publishing with ready to run native code -->
<PublishReadyToRunUseCrossgen2>true</PublishReadyToRunUseCrossgen2>
<!-- set to false to use crossgen like in 5.0 -->
<PublishReadyToRunComposite>false</PublishReadyToRunComposite>
<!-- set to true to generate a composite R2R image -->

CLI安裝.NET 6 SDK可選工作負載

.NET 6將介紹SDK工作負載的概念,可以在.NET SDK之上安裝之後,以啟用各種方案。預覽4中提供的新工作負載是.NET MAUI和Blazor WebAssembly AOT工作負載。

對於.NET MAUI工作負載,我們仍建議對預覽4使用maui-check工具,因為它包含Visual Studio中尚不可用的其他元件或作為.NET SDK工作負載。要嘗試試用.NET SDK的經驗(以iOS為例),請運行dotnet workload install microsoft-ios-sdk-full。安裝後,您可以運行,然後dotnet new ios創建和dotnet build構建您的項目。

對於Blazor WebAssembly AOT,請按照ASP.NET部落格提供的安裝說明進行操作。

預覽4包括適用於iOS,Android,tvOS,MacOS和MacCatalyst的.NET MAUI工作負載。

請注意,dotnet workload install將工作負載從NuGet.org複製到您的SDK安裝中,因此,如果SDK安裝位置受到保護(意味著在admin / root位置),則需要以高許可權/ sudo運行。

內建SDK版本檢查

為了更容易跟蹤何時有新版本的SDK和運行時,我們向.NET 6 SDK添加了新命令:dotnet sdk check

這將告訴您在每個功能範圍內什麼是.NET SDK和.NET Runtime的最新可用版本。

sdkcheck

CLI模板(dotnet new)

預覽4引入了模板的新搜尋功能。將在NuGet.org中搜索匹配的模板。在即將到來的預覽期間,用於此搜尋的資料將更頻繁地更新。dotnet new --search

CLI中安裝的模板可用於CLI和Visual Studio。解決了一個較早的問題,即在安裝新版本的SDK時,使用者安裝的模板丟失了,但是,需要重新安裝在.NET 6 Preview 4之前安裝的模板。

模板安裝的其他改進包括支援--interactive開關以支援私有NuGet提要的授權憑據。

安裝CLI模板後,您可以通過--update-check和--update-apply檢查更新是否可用。現在,這將更快地反映模板更新,支援您已定義的NuGet提要,並支援--interactive授權憑證。

在預覽4和即將釋出的預覽中,dotnet new命令的輸出將被清除以專注於您最需要的資訊。例如,dotnet new --install <package> 列表僅列出剛安裝的模板,而不列出所有模板。

為了支援對dotnet new的這些更改和即將進行的更改,我們正在對模板引擎API進行重大更改,這可能會影響託管模板引擎的任何人。這些更改將顯示在Preview 4和Preview 5中。如果您託管模板引擎,請通過https://github.com/dotnet/templating與我們聯絡,以便我們與您合作以避免或最大程度地減少干擾。

支援

.NET 6將在2021年11月釋出,並且將作為長期支援(LTS)版本獲得三年的支援。該支援平臺已顯著擴大。

新增內容包括:

  • 安卓。
  • iOS。
  • Mac和Mac Catalyst,用於x64和Apple Silicon(又稱「 M1」)。
  • Windows Arm64(特別是Windows桌面)。

.NET 6 Debian容器映像基於當前正在測試中的Debian 11(「 bullseye」)。

Closing

現在,我們可以很好地進入.NET 6版本了。雖然11月的最終版本似乎還有很長的路要走,但我們正接近完成功能開發。現在是獲得反饋的好時機,因為現已確定了新功能,並且我們仍處於積極的開發階段,因此可以隨時根據反饋採取行動。

說到11月,請在11月9日至11日預訂一些時間觀看.NET Conf 2021,肯定會令人興奮和而且會很有趣。我們將在11月9日釋出最終的.NET 6構建,並且將有一篇甚至更長的部落格文章。

還在尋找更多閱讀內容嗎?您可以檢視我們新的對話系列。有關.NET 6的新功能,有很多詳細的見解。

我們希望您享受嘗試 Preview 4。

《新程式設計師001:開發者黃金十年》

2001 年創刊,20 年技術見證

人人都是開發者 家家都是技術公司


IT145.com E-mail:sddin#qq.com