咱们很快乐公布 .NET 6 Preview 4。咱们当初大概实现了 .NET 6 公布的一半。当初是一个很好的机会,能够再次查看.NET6 的残缺范畴。许多性能都靠近最终模式,而其余性能将很快推出,因为公布的根底构建块曾经就绪。预览版 4 为在 11 月交付最终的 .NET 6 构建奠定了松软的根底,并提供了残缺的性能和体验。如果您还没有在您的环境中尝试过 .NET 6,那么您当初能够用拉。
说到最终版本,咱们当初有一个日期了!预计在 11 月 9 日至 11 日的.NET Conf 2021。咱们将在 9 日公布 .NET 6,其中蕴含许多深刻的演讲和演示,告诉您无关 .NET 6 的所有信息。
您能够下载实用于 Linux、macOS 和 Windows 的 .NET 6 预览版 4。
- 安装程序和二进制文件
- 容器镜像
- Linux 软件包
- 发行阐明
- 已知的问题
- GitHub 问题跟踪
无关 Web 和数据拜访计划的新增性能的更多详细信息,请参阅 ASP.NET Core 和 EF Core 帖子。还有新的 .NET MAUI 帖子形容了新的客户端应用程序体验,还有一个热重载帖子形容了进步开发人员生产力的新办法。
.NET 6 曾经过 Visual Studio 16.11 和 Visual Studio for Mac 8.9 的测试。如果您想在 Visual Studio 中试用 .NET 6,咱们建议您应用这些版本。
Build 2021
Microsoft 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 开发人员的内循环性能 —— 进步开发人员的工作效率,包含进步构建性能、热重启和热重载。
- 应用运行时执行信息 (PGO)进步启动和吞吐量 — 提供基于运行时信息的新模型以进步性能,可用于更快的启动、更高的吞吐量和更小的二进制文件。
- 满足开发人员的冀望 — 依据反馈在整个 .NET 产品中进行改良,并启用具备现有性能的新计划。
以下帖子更具体地探讨了其中一些主题:
- .NET 6 预览版 1
- .NET 6 预览版 2
- 对于 PGO 的对话
.NET 平台对立
咱们在过来的帖子和会议上探讨了很多对于 .NET 对立的内容,但主题中短少它。平台对立曾经融入咱们所做的所有,不须要本人的主题。人们能够将其视为超出所列主题的一个大主题。它贯通多个主题,是团队后退的根本假如。
内循环性能我的项目就是一个很好的例子。它假设 .NET 6 应用程序都共享雷同的根底,例如应用雷同的构建零碎和库。如果存在技术差别,例如应用不同的运行时(CoreCLR 或 Mono)或代码生成技术(AOT 或 JIT),咱们会思考这些因素并提供求实和适当的体验,并偏向于没有可察看到的体验差别。EventPipe 我的项目是另一个相似的例子。
产品信念
咱们将很快开始公布生产反对的 ” 上线 ” 版本。咱们目前的指标是 8 月。咱们的开发模型以启用生产工作负载为导向,即便咱们正在实现刚刚提到的所有主题的工作。
产品信念始于 dotnet.microsoft.com 站点。从预览版 1 开始,它在 .NET 6 上运行了一半的站点负载。尽管规模不大,但它是咱们团队的要害工作站点,咱们非常重视它。.NET 6 始终像冠军一样为咱们工作。
咱们还与在 .NET 预览版上部署生产应用程序的 Microsoft 团队单干。他们这样做是为了尽早利用新的 .NET 性能。这些团队始终在寻找升高云托管老本的机会,并且部署新的 .NET 版本已被证实是最无效和最省力的办法之一。这些团队为咱们提供晚期反馈,帮忙咱们确保新性能已筹备好供寰球生产应用。他们还显着影响最终特色形态,因为他们是咱们的第一批生产用户。
所有这些与理论应用程序的晚期实战测试让咱们置信 .NET 6 将筹备好运行您的应用程序。
文章的其余部分专门介绍预览版 4 中的新性能。
工具:应用 Visual Studio 调试器和 dotnet CLI 进行热重载
热重载是一种新体验,让您能够在利用程序运行时对其源代码进行编辑,而无需手动暂停应用程序或点击断点。热重载通过缩小重新启动正在运行的应用程序所需的次数来进步开发人员的工作效率。
在此版本中,热重载实用于多种类型的应用程序,例如 WPF、Windows 窗体、WinUI、ASP.NET、控制台应用程序和其余运行在 CoreCLR 运行时之上的框架。咱们也在致力将这项技术引入在 Mono 之上运行的 WebAssembly、iOS 和 Android 应用程序,但这依然会呈现(在稍后的预览版中)。
要开始测试此性能,请装置 Visual Studio 2019 版本 16.11 预览版 1 并应用 Visual Studio 调试器 (F5) 启动您的利用。利用程序运行后,您当初能够应用新的选项来更改代码并应用新的 ” 利用代码更改 ” 按钮利用它们,如下图所示。
热重载也可通过 dotnet 监督工具取得。预览版 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 性能为 System.Text.Json 增加了一个新的简略高效的编程模型。这个新的 API 很有吸引力,因为它防止了序列化的复杂性和典礼以及 DOM 的传统老本。
这个新的 API 有以下益处:
- 在不可能或不心愿应用 POCO 类型的状况下,或者当 JSON 模式不固定且必须查看时,序列化的轻量级代替计划。
- 容许对大树的子集进行无效批改。例如,能够高效地导航到大型 JSON 树的子局部并从该子局部读取数组或反序列化 POCO。LINQ 也能够与它一起应用。
- 容许应用 C# 动静关键字,这容许应用涣散类型的、更像脚本的模型。
咱们正在寻找无关反对动静的反馈。如果动静反对对您很重要,请给咱们您的反馈。
在 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 命名空间的一部分,应用时,它会生成 performant 日志 API。源代码生成日志反对旨在为古代 .NET 应用程序提供高度可用且高性能的日志解决方案。主动生成的源代码依赖于 ILogger 接口和 LoggerMessage.Define 性能。
当 LoggerMessageAttribute 用于局部日志记录办法时,将触发源生成器。当被触发时,它要么可能主动生成它正在装璜的局部办法的实现,要么产生带有正确应用提醒的编译时诊断。编译时日志记录解决方案在运行时通常比现有日志记录办法快得多。它通过最大限度地打消装箱、长期调配和拷贝来实现这一点。
间接手动应用 LoggerMessage.Define API 有以下益处:
- 更短更简略的语法:申明性属性应用而不是代码样板。
- 疏导开发者体验:生成器给出正告,帮忙开发者做正确的事。
- 反对任意数量的日志参数。LoggerMessage.Define 最多反对六个。
- 反对动静日志级别。独自应用 LoggerMessage.Define 是不可能的。
- 如果您想跟踪改良和已知问题,请参阅 dotnet/runtime\#52549。
根本用法
要应用 LoggerMessageAttribute,消费类和办法须要是局部的。
代码生成器在编译时触发,并生成局部办法的实现。
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);
}
在后面的示例中,日志记录办法是动态的,并且在属性定义中指定了日志级别。在动态上下文中应用该属性时,须要 ILogger 实例作为参数。您也能够抉择在非动态上下文中应用该属性。无关更多示例和应用场景,请拜访编译时日志源生成器的文档。
System.Linq 加强性能
增加了社区申请和奉献的新 System.LINQ API。
对索引和范畴参数的可枚举反对
Enumerable.ElementAt 办法当初承受可枚举对象开端的索引,如下例所示。
Enumerable.Range(1, 10).ElementAt(\^2); // returns 9
增加了承受 Range 参数的 Enumerable.Take 重载。它简化了可枚举序列的切片:
- 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
新的变体已增加到 set 操作中,容许应用键选择器函数指定相等性,如上面的示例所示。
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 重载
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 重写:应用 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
“
环境:Windows 10 与 SSD 驱动器启用 BitLocker
后果:
- 当初读取 1 MB 文件的速度进步了 2 倍,而写入的速度进步了 4 倍。
- 内存调配从 39 KB 降落到 1 KB!这是 97.5% 的改良!
这些更改将为 Windows 上的 FileStream 用户提供显着的改良。更多详细信息,请拜访 dotnet/core #6098。
加强的日期、工夫和时区反对
对日期和工夫相干的类型进行了以下改良。
新的 DateOnly 和 TimeOnly 构造
增加了仅限日期和工夫的构造,具备以下特色:
- 每个代表一个 DateTime 的一半,或者只是日期局部,或者只是工夫局部。
- DateOnly 是生日、周年纪念日和工作日的现实抉择。它与 SQL Server 的日期类型统一。
- TimeOnly 是定期会议、闹钟和每周工作工夫的现实抉择。它与 SQL Server 的工夫类型统一。
- 补充现有的日期 / 工夫类型(DateTime、DateTimeOffset、TimeSpan、TimeZoneInfo)。
- 在 System 命名空间中,在 CoreLib 中提供,就像现有的相干类型一样。
对 DateTime.UtcNow 的性能改良
这种改良有以下益处:
- 修复了在 Windows 上获取零碎工夫的 2.5 倍性能回归。
- 利用 Windows 闰秒数据的 5 分钟滑动缓存,而不是在每次调用时获取。
反对所有平台上的 Windows 和 IANA 时区
这种改良有以下益处:
- 应用 TimeZoneInfo.FindSystemTimeZoneById 时的隐式转换 (https://github.com/dotnet/runtime/pull/49412)
- 通过 TimeZoneInfo 上的新 API 进行显式转换:TryConvertIanaIdToWindowsId、TryConvertWindowsIdToIanaId
和 HasIanaId (https://github.com/dotnet/runtime/issues/49407) - 改良了应用不同时区类型的零碎之间的跨平台反对和互操作。
- 删除须要应用 TimeZoneConverter OSS 库。该性能现已内置。
改良的时区显示名称
这种改良有以下益处:
- 从 TimeZoneInfo.GetSystemTimeZones 返回的列表中的显示名称中打消歧义。
- 利用 ICU / CLDR 全球化数据。
- 仅实用于 Unix。Windows 依然应用注册表数据。这可能会在当前更改。
其余
- UTC 时区的显示名称和规范名称被硬编码为英语,当初应用与其余时区数据雷同的语言(Unix 上的 CurrentUICulture,Windows 上的操作系统默认语言)。
- 因为大小限度,WASM 中的时区显示名称改为应用非本地化的 IANA ID。
- TimeZoneInfo.AdjustmentRule 嵌套类将其 BaseUtcOffsetDelta 外部属性设为公开,并取得一个以 baseUtcOffsetDelta 作为参数的新构造函数。(https://github.com/dotnet/runtime/issues/50256
- TimeZoneInfo.AdjustmentRule 还取得了在 Unix 上加载时区的其余修复(https://github.com/dotnet/run…),(https://github.com/dotnet/run…)
CodeGen
对 RyuJIT 编译器进行了以下改良。
社区奉献
@SingleAccretion 在过来几个月中始终忙于进行以下改良。这是 .NET 6 Preview 3 的补充。谢谢!
- dotnet/runtime #50373 — 如果树是 CSE 候选者,不要折叠双重否定
- dotnet/runtime #50450 — 解决通过助手实现的转换和值编号中的折叠溢出操作
- dotnet/runtime #50702 — 删除 GS Cookie 的 must-init 要求
- 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 — 针对 ref 类型的初始化动态只读字段折叠空查看
- dotnet/runtime #50112 — 不要在潜在的 BBJ_THROW 候选中调配字符串文字
- dotnet/runtime #50644 — 为 VectorX.Create 启用 CSE
- dotnet/runtime #50806 — 如果前面有意外的块,则放弃尾调用
- dotnet/runtime #50832 — 更新 Vector<T> 以反对 nint 和 nuint
- dotnet/runtime #51409 — 概括围绕空流优化的分支
.NET 诊断:EventPipe for Mono 和改良的 EventPipe 性能
EventPipe 是 .NET 的跨平台机制,用于输入事件、性能数据和计数器。从 .NET 6 开始,咱们已将实现从 C++ 移至 C。通过此更改,Mono 也将可能应用 EventPipe!这意味着 CoreCLR 和 Mono 将应用雷同的事件根底构造,包含 .NET 诊断 CLI 工具!这一变动还随同着 CoreCLR 的小幅缩减:
咱们还进行了一些更改,以进步负载下的 EventPipe 吞吐量。在前几个预览版中,咱们进行了一系列更改,使吞吐量进步了 .NET 5 所能达到的 2.06 倍:
- 应用 dotnet/diagnostics 中的 EventPipeStress 框架收集的数据。编写器应用程序在 60 秒内尽可能快地写入事件。记录胜利和抛弃事件的数量。
无关详细信息,请参阅 dotnet/runtime #45518。
IL 剪裁
默认启用正告
剪裁正告告诉您剪裁可能会删除运行时应用的代码的中央。这些正告以前在默认状况下被禁用,因为正告十分嘈杂,次要是因为.NET 平台没有作为第一类计划参加剪裁。
咱们对 .NET 库(运行时库,而不是 ASP.NET Core 或 Windows 桌面框架)的大部分进行了正文,以便它们生成精确的剪裁正告。因而,咱们认为是时候默认启用剪裁正告了。
您能够通过将 <SuppressTrimAnalysisWarnings> 设置为 true 来禁用正告。对于晚期版本,您能够将雷同的属性设置为 false 以查看剪裁正告。
剪裁正告为剪裁过程带来了可预测性,并使开发人员把握了势力。咱们将持续正文更多 .NET 库,包含后续版本中的 ASP.NET Core。咱们心愿社区也能通过正文更多代码以确保安剪裁全来改善剪裁生态系统。
更多信息:
- .NET 6 中的剪裁正告
- 筹备 .NET 库以进行剪裁
默认 剪裁 模式 = 链接
.NET 6 中新的默认剪裁模式是链接。链接 TrimMode 不仅能够剪裁未应用的程序集,还能够剪裁未应用的成员,从而显着节省成本。
在 .NET 5 中,默认状况下剪裁会尝试查找和删除未援用的程序集。这更平安,但提供的益处无限。当初默认状况下剪裁正告处于启用状态,开发人员能够对剪裁后果充满信心。
作为示例,让咱们通过剪裁其中一个 .NET SDK 工具来看看这种剪裁改良。
我将应用 crossgen,即筹备运行的编译器。它能够只用一些剪裁正告来剪裁,crossgen 团队可能解决这些问题。
首先,让咱们将 crossgen 公布为一个独立的应用程序,无需剪裁。它是 80
MB(包含 .NET 运行时和所有库)。
而后咱们能够尝试(当初是旧版).NET 5 默认剪裁模式,copyused。后果降落到 55 MB。
新的 .NET 6 默认剪裁模式链接将独立文件大小进一步升高到 36MB。
咱们心愿新的链接剪裁模式能更好地满足剪裁的冀望:显着节俭和可预测的后果。
与 Native AOT 共享模型
咱们也为 Native AOT 试验施行了雷同的剪裁正告,这应该会以大致相同的形式改善 Native AOT 编译体验。
单文件公布
对单文件应用程序公布进行了以下改良。
动态剖析
.NET 5 中增加了用于单文件公布的分析器,以正告 Assembly.Location
和其余一些在单文件包中体现不同的 API。
对于 .NET 6 Preview 4,咱们改良了剖析以容许自定义正告。如果您的 API 在单文件公布中不起作用,您当初能够应用 [RequiresAssemblyFiles] 属性对其进行标记,如果启用了分析器,则会呈现正告。增加该属性还将使办法中与单个文件相干的所有正告静音,因而您能够应用该正告将正告向上流传到您的公共 API。
当 PublishSingleFile 设置为 true 时,分析器会主动为 exe 我的项目启用,但您也能够通过将 EnableSingleFileAnalysis 设置为 true 为任何我的项目启用它。如果您想在单个文件包中嵌入库,这可能会有所帮忙。
压缩
单文件包当初反对压缩,这能够通过将属性 EnableCompressionInSingleFile 设置为 true 来启用。在运行时,依据须要将文件解压缩到内存中。压缩能够为某些场景提供微小的空间节俭。
让咱们看一下与 NuGet 包资源管理器一起应用的带压缩和不带压缩的单个文件公布。
无压缩:172 MB
压缩后:71.6 MB
压缩能够显着减少应用程序的启动工夫,尤其是在 Unix 平台上(因为它们具备无奈与压缩一起应用的无复制疾速启动门路)。您应该在启用压缩后测试您的利用,看看额定的启动老本是否能够承受。
PublishReadyToRun 当初默认应用 crossgen2
Crossgen2 当初在公布 ReadyToRun 图像时默认启用。它还可选地反对生成合成图像。
公开以下设置,使您可能应用筹备运行的代码配置公布。这些设置被设为它们的默认值。
PublishReadyToRun 当初默认应用 crossgen2
Crossgen2 当初在公布 ReadyToRun 图像时默认启用。它还可选地反对生成合成图像。
公开以下设置,使您可能应用筹备运行的代码配置公布。这些设置被设为它们的默认值。
.NET 6 SDK 可选工作负载的 CLI 装置
.NET 6 将引入能够预先装置在 .NET SDK 之上的 SDK 工作负载的概念,以反对各种场景。预览版 4 中可用的新工作负载是 .NET MAUI 和 Blazor WebAssembly AOT 工作负载。
对于 .NET MAUI 工作负载,咱们依然倡议应用预览版 4 的 maui-check
工具,因为它蕴含 Visual Studio 中尚不可用的其余组件或作为 .NET SDK 工作负载。要尝试 .NET SDK 体验(以 iOS 为例),请运行 dotnet working install microsoft-ios-sdk-full。装置后,您能够运行 dotnet new ios,而后运行 dotnet build 来创立和构建您的我的项目。
对于 Blazor WebAssembly AOT,请依照 ASP.NET 博客提供的装置阐明进行操作。
预览版 4 包含实用于 iOS、Android、tvOS、MacOS 和 MacCatalyst 的 .NET MAUI 工作负载。
请留神,dotnet 工作负载装置会将工作负载从 NuGet.org 复制到您的 SDK 装置中,因而如果 SDK 装置地位受到爱护(意味着在管理员 / 根地位),则须要运行晋升 /sudo。
内置 SDK 版本查看
为了更轻松地跟踪新版本的 SDK 和运行时何时可用,咱们向 .NET 6 SDK 增加了一个新命令:dotnet sdk check
这将告诉您在每个性能带内什么是 .NET SDK 和 .NET 运行时的最新可用版本。
CLI 模板 (dotnet new)
预览版 4 引入了新的模板搜寻性能。dotnet new –search 将在 NuGet.org
中搜寻匹配模板。在行将进行的预览期间,用于此搜寻的数据将更频繁地更新。
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 进行重大更改,这可能会影响托管模板引擎的任何人。这些更改将呈现在预览版 4 和预览版 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”),目前正在测试中。
完结
此时咱们曾经进入 .NET 6 版本。尽管 11 月的最终版本仿佛还有很长的路要走,但咱们已靠近实现性能开发。当初是反馈的好时机,因为新性能的形态当初曾经确定,而且咱们仍处于踊跃的开发阶段,因而能够很容易地依据反馈采取行动。
说到 11 月,请在 11 月 9 日至 11 日期间预订一些工夫观看 .NET Conf 2021。这必定会令人兴奋和乏味。咱们将在 11 月 9 日公布最终的 .NET 6 版本,以及比这一篇更长的博文。
还在寻找更多浏览?您能够查看咱们的新对话系列。有很多对于 .NET 6 新性能的具体见解。有任何技术问题,请在 Microsoft Q&A 上发问.
咱们心愿您喜爱试用预览版 4。