.NET 6 Preview 5 发布
我们很高兴发布 .NET 6 Preview 5。我们现在正处于 .NET 6 发布的下半部分,并且开始看到重要的功能整合在一起。一个很好的例子是 .NET SDK 工作负载,它是我们.NET 统一愿景的基础,可以支持更多的应用程序类型。与其他功能一样,它结合在一起以提供引人注目的端到端用户体验。
您可以下载适用于 Linux、macOS 和 Windows 的.NET 6 Preview 5。
安装程序和二进制文件
容器镜像
Linux 软件包
发行说明
API差异
已知的问题
GitHub 问题跟踪器
请参阅ASP.NET Core、 EF Core和.NET MAUI帖子,了解有关 Web、数据访问和跨平台 UI 方案的新增功能的更多详细信息。
Visual Studio 2022 Preview 1 也在今天发布,.NET 6 Preview 5 包含在该版本中。.NET 6 还通过Visual Studio 16.11和Visual Studio for Mac 8.9 进行了测试。如果您想在Visual Studio 中试用 .NET 6,我们建议您使用这些版本。
可以查看新的对话帖子,以深入了解工程师对最新 .NET 功能的讨论。
.NET SDK:可选的工作负载改进
SDK 工作负载是一项新的 .NET SDK 功能,它使我们能够在不增加 SDK 大小的情况下添加对新应用程序类型(如 Mobile 和 WebAssembly)的支持。
工作负载功能已更新为支持list
和update
。这些新功能提供了预期的最终体验。您将能够使用一些简单的命令快速建立您喜欢的环境,并随着时间的推移保持最新状态。
dotnet workload list
会告诉您安装了哪些工作负载。dotnet workload update
将所有已安装的工作负载更新到最新的可用版本。
update
查询 nuget.org 更新的工作负载清单、更新本地清单、下载已安装工作负载的新版本,然后删除工作负载的所有旧版本。这类似于 apt update和 apt upgrade -y(用于基于 Debian 的 Linux 发行版)。
这些 dotnet workload
命令在给定 SDK 的上下文中运行。假设您同时安装了 .NET 6 和 .NET 7。如果您同时使用两者,则工作负载命令将提供不同的结果,因为工作负载会有所不同(至少是相同工作负载的不同版本)。
如您所见,工作负载功能本质上是 .NET SDK 的包管理器。工作负载最初是在.NET 6 预览版 4版本中引入的。
.NET SDK:NuGet 包验证
包验证工具将使 NuGet 库开发人员能够验证他们的包是否一致且格式良好。
这包括:
验证跨版本没有重大更改。
验证包对于所有特定于运行时的实现是否具有相同的公共 API 集。
确定任何目标框架或运行时适用性差距。
此工具可通过Microsoft.DotNet.PackageValidation 获得。
很快就会发布有关此工具的帖子。
.NET SDK:更多 Roslyn 分析器
在 .NET 5 中,我们随 .NET SDK 提供了大约 250 个分析器。其中许多已经存在,但之前并未作为 NuGet 包发布。我们正在为 .NET 6 添加更多分析器。
默认情况下,大多数新分析器在信息级别启用。您可以通过下面的方式配置这些分析器在警告级别的分析模式:<AnalysisMode>AllEnabledByDefault</AnalysisMode>
我们发布了我们想要的 .NET 6 分析器集(加上一些额外的东西),然后将其中的大部分都准备好了。
感谢 Newell Clark 和 Meik Tranel 以下的实现,包括在了 Preview 5 中。注意社区在以前的预览版本中的贡献了其他实现。
| 贡献者 | 问题 | 标题 |
|---|---|---|
| Newell Clark | dotnet/runtime#33777 | 使用基于 Span 的 string.Concat |
| Newell Clark | dotnet/runtime#33784 | 在解析时使用 string.AsSpan() 代替 string.Substring() |
| Newell Clark | dotnet/runtime#33789 | Stream.ReadAsync/WriteAsync重载 |
| Newell Clark | dotnet/runtime#35343 | 将 Dictionary<,>.Keys.Contains替换为 ContainsKey |
| Newell Clark | dotnet/runtime#45552 | 使用String.Equals代替String.Compare |
| Meik Tranel | dotnet/runtime#47180 | 使用 String.Contains(char) 代替 String.Contains(String) |
.NET SDK:为平台兼容性分析器启用自定义防护
CA1416 平台兼容性分析器已经使用 OperatingSystem/RuntimeInformation 中的方法(例如OperatingSystem.IsWindows和OperatingSystem.IsWindowsVersionAtLeast )识别平台防护。但是,分析器不会识别任何其他保护可能性,例如缓存在字段或属性中的平台检查结果,或者在辅助方法中定义了复杂的平台检查逻辑。
为了允许自定义保护的可能性,我们添加了新属性 SupportedOSPlatformGuard
并UnsupportedOSPlatformGuard
使用相应的平台名称和/或版本注释自定义保护成员。该注释被平台兼容性分析器的流分析逻辑所识别和尊重。
用法
[UnsupportedOSPlatformGuard("browser")] // The platform guard attribute#if TARGET_BROWSER
internal bool IsSupported => false;#else
internal bool IsSupported => true;#endif
[UnsupportedOSPlatform("browser")]
void ApiNotSupportedOnBrowser() { }
void M1()
{
ApiNotSupportedOnBrowser(); // Warns: This call site is reachable on all platforms.'ApiNotSupportedOnBrowser()' is unsupported on: 'browser'
if (IsSupported)
{
ApiNotSupportedOnBrowser(); // Not warn
}
}
[SupportedOSPlatform("Windows")]
[SupportedOSPlatform("Linux")]
void ApiOnlyWorkOnWindowsLinux() { }
[SupportedOSPlatformGuard("Linux")]
[SupportedOSPlatformGuard("Windows")]
private readonly bool _isWindowOrLinux = OperatingSystem.IsLinux() || OperatingSystem.IsWindows();
void M2()
{
ApiOnlyWorkOnWindowsLinux(); // This call site is reachable on all platforms.'ApiOnlyWorkOnWindowsLinux()' is only supported on: 'Linux', 'Windows'.
if (_isWindowOrLinux)
{
ApiOnlyWorkOnWindowsLinux(); // Not warn
}
}
}
Windows Forms:默认字体
现在,您可以使用Application.SetDefaultFont设置默认字体的应用程序。您使用的模式类似于设置高 dpi 或 VisualStyles。
class Program{
[STAThread]
static void Main()
{
Application.SetHighDpiMode(HighDpiMode.SystemAware);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.SetDefaultFont(new Font(new FontFamily("Microsoft Sans Serif"), 8f));
Application.Run(new Form1());
}}
下面是设置默认字体后的两个示例(使用不同的字体)。
Microsoft Sans Serif, 8pt:

Chiller,12pt:

该默认字体在.NET Core 3.0 更新中引入。然而,这一变化为一些用户将 .NET Framework 应用程序迁移到 .NET Core 带来了重大障碍。这一新变化使为应用程序选择所需字体变得简单,并消除了迁移障碍。
库:放弃对旧框架的支持
从包中删除框架是一个源代码上破坏性的更改。同时,继续为我们发布的所有框架构建会增加包的复杂性和大小。过去,我们通过收获 解决了这个问题,这基本上意味着:
我们只为当前框架构建
在构建期间,我们下载包的早期版本,并为我们不再构建的早期框架过期的二进制文件
虽然这意味着您可以随时更新而不必担心我们会删除框架,但这也意味着如果您使用不受支持的二进制文件,您将永远不会获得任何错误修复或新功能。换句话说,不受支持的产品无法提供服务,现在隐藏了,因为从您的角度来看,即使您正在使用我们不再使用的旧二进制文件,您也可以继续将包更新到更高版本更新。
从 .NET 6 Preview 5 开始,我们计划不再执行任何形式的付出,以确保我们交付的所有产品都可以得到服务支持。这意味着我们将放弃对比这些更旧的任何框架的支持:
.NET Framework 4.6.1
.NET Core 3.1
.NET Standard 2.0
如果您当前正在引用来自早期框架的受影响包,您将无法再将引用的包更新到更高版本。您的选择是将您的项目重新定位到更高的框架版本,或者不更新引用的包(这通常不是一个巨大的好处,因为无论如何您已经在使用冻结的二进制文件)。
有关更多详细信息,包括受影响软件包的完整列表,请参阅dotnet/announcement: Dropping old framework versions。
库:Microsoft.Extensions
我们一直在改进此版本的 Microsoft.Extensions API。在预览版 5 中,我们专注于托管和依赖注入。在预览版 4 中,我们添加了一个用于 logging的编译时源生成器。
感谢 Martin Björkström(https://github.com/bjorkstromm) 的dotnet/runtime #51840 (AsyncServiceScope)。
托管 – ConfigureHostOptions API
我们在 IHostBuilder 上添加了一个新的 ConfigureHostOptions API 以简化应用程序设置(例如配置关闭超时):
using HostBuilder host = new()
.ConfigureHostOptions(o =>
{
o.ShutdownTimeout = TimeSpan.FromMinutes(10);
})
.Build();
host.Run();
在 Preview 5 之前,配置主机选项有点复杂,如下:
using HostBuilder host = new()
.ConfigureServices(services =>
{
services.Configure<HostOptions>(o =>
{
o.ShutdownTimeout = TimeSpan.FromMinutes(10);
});
})
.Build();
host.Run();
依赖注入 – CreateAsyncScope API
您可能已经注意到,在注册 IAsyncDisposable 服务时,服务提供者的处置会抛出 InvalidOperationException。
新 CreateAsyncScope
API 提供了一个简单的解决方案,如以下示例所示:
await using (var scope = provider.CreateAsyncScope())
{
var foo = scope.ServiceProvider.GetRequiredService<Foo>();
}
以下示例演示了现有的问题案例,然后演示了之前建议的解决方法。
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
await using var provider = new ServiceCollection().AddScoped<Foo>()
.BuildServiceProvider();
// This using can throw InvalidOperationException
using (var scope = provider.CreateScope())
{
var foo = scope.ServiceProvider.GetRequiredService<Foo>();}
class Foo : IAsyncDisposable
{
public ValueTask DisposeAsync() => default;
}
您可以通过将返回的范围强制转换为IAsyncDisposable
.
var scope = provider.CreateScope();
var foo = scope.ServiceProvider.GetRequiredService<Foo>();
await ((IAsyncDisposable)scope).DisposeAsync();
CreateAsyncScope
解决了这个问题,使您可以安全地使用using
语句。
库:JsonSerializer
源代码生成
几乎所有 .NET 序列化程序的支柱都是反射。反射对于某些场景来说是一项很棒的功能,但不能作为高性能云原生应用程序(通常(反)序列化和处理大量 JSON 文档)的基础。反射会是启动、内存使用和程序集修剪的一个问题。
运行时反射的替代方法是编译时源代码生成。源代码生成器生成 C# 源文件,这些文件可以作为库或应用程序构建的一部分进行编译。在编译时生成源代码可以为 .NET 应用程序提供许多好处,包括提高性能。
在 .NET 6 中,我们将一个新的源生成器作为System.Text.JsonJsonSerializer
的一部分. JSON 源生成器与 JsonSerializer 配合使用,并且可以通过多种方式进行配置。是否使用新的源生成器由您决定。它可以提供以下好处:
减少启动时间
提高序列化吞吐量
减少私有内存使用
删除运行时使用System.Reflection和
System.Reflection.Emit允许修剪兼容的 JSON 序列化
例如,不是在运行时使用Reflection.Emit动态生成方法来在(反)序列化期间使用(使用私有内存并具有启动成本)来获取和设置类属性,而源生成器可以生成更简单有效地分配或检索类属性的代码。直接从属性中获取值,速度快如闪电
您可以使用 System.Text.Json NuGet 包的最新预览版来试用源生成器。我们正在制定在 SDK 中包含源生成器的提案。
生成优化的序列化逻辑
默认情况下,JSON 源生成器为给定的可序列化类型发出序列化逻辑。JsonSerializer
通过生成Utf8JsonWriter
直接使用的源代码,这提供了比使用现有方法更高的性能。简而言之,源代码生成器提供了一种在编译时为您提供不同实现的方法,以便使运行时体验更好。
缩小JsonSerializer
是一个强大的工具,它具有许多功能(甚至更多功能!),可以改进 .NET 类型从/到 JSON 格式的(反)序列化。它很快,但是当序列化例程只需要一个功能子集时,它会产生一些性能开销。展望未来,我们将一起更新JsonSerializer
和新的源生成器。
给定一个简单类型:
namespace Test
{internal class JsonMessage
{
public string Message { get; set; }
}
}
源生成器可以配置为为示例JsonMessage
类型的实例生成序列化逻辑。请注意,类名JsonContext
是任意的。您可以为生成的源使用任何您想要的类名。
using System.Text.Json.Serialization;
namespace Test
{[JsonSerializable(typeof(JsonMessage)]
internal partial class JsonContext : JsonSerializerContext
{
}
}
我们定义了一组由JsonSerializer
源生成模式支持的功能,这些模式提供了最佳的序列化吞吐量,通过JsonSerializerOptionsAttribute
. 这些功能可以提前指定给源生成器,以避免在运行时进行额外检查。如果未使用该属性,则JsonSerializationOptions
在运行时假定为默认值。
作为构建的一部分,源生成器JsonContext
使用以下形状扩充部分类:
internal partial class JsonContext : JsonSerializerContext
{public static JsonContext Default { get; }
public JsonTypeInfo<JsonMessage> JsonMessage { get; }
public JsonContext(JsonSerializerOptions options) { }
public override JsonTypeInfo GetTypeInfo(Type type) => ...;
}
使用此模式的序列化程序调用可能类似于以下示例。此示例提供了可能的最佳性能。
using MemoryStream ms = new();
using Utf8JsonWriter writer = new(ms);
JsonContext.Default.JsonMessage.Serialize(writer, new JsonMessage { "Hello, world!" });
writer.Flush();
// Writer contains:
// {"Message":"Hello, world!"}
或者,您可以继续使用JsonSerializer
,代替将生成的代码的实例传递给它,使用 JsonContext.Default.JsonMessage
JsonSerializer.Serialize(jsonMessage, JsonContext.Default.JsonMessage);
这是一个类似的用法,但具有不同的重载。
JsonSerializer.Serialize(jsonMessage, typeof(JsonMessage), JsonContext.Default);
这两个重载之间的区别在于,第一个是使用类型化元数据实现—JsonTypeInfo<T>—第二个是使用更通用的非类型化实现,它进行类型测试以确定上下文实例中是否存在类型化实现。因此,它有点慢(由于类型测试)。如果给定类型没有源生成的实现,则序列化程序会抛出一个NotSupportedException. 它不会回退到基于反射的实现(作为显式设计选择)。
最快、最优化的源代码生成模式——基于Utf8JsonWriter
——目前仅可用于序列化。Utf8JsonReader
根据您的反馈,将来可能会提供类似的反序列化支持(基于)。
但是,源生成器还生成类型元数据初始化逻辑,这也有助于反序列化。要反序列化JsonMessage
使用预生成类型元数据的实例,您可以执行以下操作:
JsonSerializer.Deserialize(json, JsonContext.Default.JsonMessage);
类似于上面的序列化,你也可以这样写:
JsonSerializer.Deserialize(json, typeof(JsonMessage), JsonContext.Default);
补充笔记
可以通过[JsonSerializable]派生的JsonSerializerContext部分实例为源生成包含多种类型(而不仅仅是一种)。
源生成器还支持对象上的嵌套对象和集合成员,而不仅仅是基元类型。
库:WebSocket 压缩
压缩对于通过网络传输的任何数据都很重要。WebSockets 现在启用压缩。我们使用了WebSockets 扩展的实现permessage-deflate,RFC 7692。它允许使用 DEFLATE 算法压缩 WebSockets 消息 payload。
此功能是用户对 GitHub 上 Networking 的最高要求之一。您可以通过API 审核 1和API 审核 2跟随我们提供该 API 的过程。
感谢 Ivan Zlatanov。谢谢 Ivan!
我们意识到将压缩与加密结合使用可能会导致攻击,例如CRIME和BREACH。这意味着不能在单个压缩上下文中将私密信息与用户生成的数据一起发送,否则可以提取该私密信息。为了让用户注意这些影响并帮助他们权衡风险,我们将 API 重命名为DangerousDeflateOptions
. 我们还添加了对特定消息关闭压缩的功能,因此如果用户想要发送私密信息,他们可以在不压缩的情况下安全地发送。
Ivan还进行了一项后续工作,当禁用压缩时,WebSocket 的内存占用减少了约 27%。
从客户端启用压缩很容易,请参见下面的示例。但是,请记住服务器可以协商设置,例如请求较小的窗口,或完全拒绝压缩。
var cws = new ClientWebSocket();
cws.Options.DangerousDeflateOptions = new WebSocketDeflateOptions()
{ClientMaxWindowBits = 10,
ServerMaxWindowBits = 10
};
最近还添加了对 ASP.NET Core 的 WebSocket 压缩支持。它将包含在即将发布的预览版本中。
库:Socks 代理支持
SOCKS是一种代理服务器实现,可以处理任何 TCP 或 UDP 流量,使其成为一个非常通用的系统。这是一个长期存在的社区请求,已添加到 .NET 6 中。
此更改增加了对 Socks4、Socks4a 和 Socks5 的支持。例如,它允许通过 SSH 测试外部连接或连接到 Tor 网络。
WebProxy
现在可以接受socks
的协议,你可以在下面的例子中看到。
var handler = new HttpClientHandler
{
Proxy = new WebProxy("socks5://127.0.0.1", 9050)
};
var httpClient = new HttpClient(handler);
感谢 Huo Yaoyuan。谢谢 Huo!
库:支持 OpenTelemetry 指标
我们一直在为最后几个 .NET 版本添加对 OpenTelemetry 的支持,作为我们对可观察性的关注的一部分。在 .NET 6 中,我们添加了对OpenTelemetry Metrics API 的支持。通过添加对 OpenTelemetry 的支持,您的应用程序可以与其他OpenTelemetry系统无缝互操作。
System.Diagnostics.Metrics是OpenTelemetry Metrics API 规范的 .NET 实现。Metrics API 是专门为处理原始指标数据而设计的,通常旨在高效且同时地生成这些测量的连续摘要。
API 包括Meter
可用于创建仪器对象(例如计数器)的类。这些API暴露四个类:Counter
,Histogram
,ObservableCounter
,ObservableGauge
支持不同的指标方案。此外,API 公开MeterListener
该类以允许侦听的记录测量以进行聚合和分组。
该OpenTelemetry .NET实现将扩展到使用这些新的API,其中新增的指标可观察方案的支持。
库指标数据记录示例
Meter meter = new Meter("io.opentelemetry.contrib.mongodb", "v1.0");
Counter<int> counter = meter.CreateCounter<int>("Requests");
counter.Add(1);
counter.Add(1, KeyValuePair.Create<string, object>("request", "read"));
监听示例
MeterListener listener = new MeterListener();
listener.InstrumentPublished = (instrument, meterListener) =>
{
if (instrument.Name == "Requests" && instrument.Meter.Name == "io.opentelemetry.contrib.mongodb")
{
meterListener.EnableMeasurementEvents(instrument, null);
}
};
listener.SetMeasurementEventCallback<int>((instrument, measurement, tags, state) =>
{
Console.WriteLine($"Instrument: {instrument.Name} has recorded the measurement {measurement}");
});
listener.Start();
库:BigInteger 性能
从十进制和十六进制字符串解析 BigIntegers已得到改进。我们看到了高达 89% 的改进,如下图所示。

这归功于 Joseph Da Silva。谢谢 Joseph!
库:现在Vector<T>
支持nint
和nuint
Vector<T>
现在支持C# 9 中添加的原始类型nint
和nuint
。此更改应该可以更轻松地使用带有指针或平台相关长度的 SIMD 指令。
库:支持 OpenSSL 3
.NET 加密 API 支持使用OpenSSL 3作为 Linux 上的首选本机加密提供程序。如果可用,.NET 6 将使用 OpenSSL 3。否则,它将使用 OpenSSL 1.x。
库:添加支持 ChaCha20/Poly1305 加密算法
ChaCha20Poly1305
已添加到System.Security.Cryptography。要使用ChaCha20/Poly1305算法,必须得到底层操作系统的支持。静态属性IsSupported 可用于确定在给定上下文中是否支持该算法。
Linux:需要 OpenSSL 1.1 或更高版本。
Windows:构建 20142 或更高版本(目前需要开发“内部人员”频道)
感谢 Kevin Jones 对Linux的支持。谢谢 Kevin!
互操作性:Objective-C 互操作性支持
团队一直在添加 Objective-C 支持,目标是为 .NET提供单一的Objective-C 互操作实现。到目前为止,Objective-C互操作系统是围绕 Mono 嵌入 API 构建的,但我们认为这不是跨运行时共享的正确方法。因此,我们创建了一个新的 .NET API,它将支持单一的 Objective-C 互操作体验,最终将在两个运行时上运行。
这个用于 Objective-C 互操作的新 API 为 的两个运行时带来了直接支持NSAutoreleasePool
,从而支持Cocoa 的引用计数内存管理系统。您现在可以配置是否希望每个托管线程都具有隐式NSAutoreleasePool
. 这使得在每个线程的基础上释放 Cocoa 对象成为可能。
诊断(EventPipe/DiagnosticsServer)——MonoVM
从 .NET 6 开始,MonoVM 中添加了许多诊断功能。这启用了托管 EventSource/EventListener、EventPipe 和 DiagnosticsServer 等功能。它支持使用dotnet-trace、dotnet-counters、dotnet-stacks等诊断工具,用于在移动设备 (iOS/Android) 和桌面上运行的应用程序。
这些新功能开启了在 PrefView/SpeedScope/Chromium、dotnet-trace等工具中分析 MonoVM 生成的 nettrace 文件的能力,或使用TraceEvent 等库编写自定义解析器。
我们将继续包含更多功能,主要侧重于 SDK 集成,并将更多 native runtime events (Microsoft-Windows-DotNETRuntime )适配到 MonoVM 中,从而在 nettrace 文件中启用更多事件。
现已具备以下功能:
在 MonoVM 和 CoreCLR 之间共享 Native EventPipe/DiagnosticsServer 库。
将 TCP/IP 支持添加到 DiagnosticsServer 并利用该配置构建 MonoVM iOS/Android 运行时包。支持移动平台需要。
BCL EventSources 在 MonoVM 上运行,将事件发送到 EventPipe。
BCL 运行时计数器由System.Diagnostics.Tracing.RuntimeEventSource连接到 MonoVM发出,可从
dotnet-counters消费自定义事件源在 MonoVM 上运行,将自定义事件发送到 EventPipe,可从
dotnet-trace消费自定义事件计数器在 MonoVM 上运行,将自定义计数器事件发送到 EventPipe,可从
dotnet-counters消费采样分析器在 MonoVM 上实现,将事件发送到 EventPipe。支持了使用
dotnet-trace
做的MonoVM CPU评测实现dotnet-dsrouter诊断工具,能够利用现有的诊断工具一样,dotnet-trace,dotnet-counters,dotnet-counters对Mobile的运行时MonoVM,而不需要共同改变现有的工具。
dotnet-stackdotnet-dsrouter
运行本地 IPC 服务器,将所有流量从诊断工具路由到在模拟器/设备上的 MonoVM 中运行的 DiagnosticsServer。使用基于组件的架构在 MonoVM 中实现 EventPipe/DiagnosticsServer 。
基于文件会话的诊断环境的实现/扩展。
iOS CPU 采样(SpeedScope)
下图演示了在 SpeedScope 中查看的 iOS 启动 CPU 采样会话的一部分。

Android CPU 采样 (PerfView)
下图演示了在 PerfView(无限睡眠中的主线程)中查看的 Android CPU 采样。

运行时:CodeGen
RyuJIT 中进行了以下更改。
社区贡献
删除未使用的 dummyBB 变量 https://github.com/dotnet/runtime/pull/52155
删除未使用的函数,以大端格式读取整数 https://github.com/dotnet/runtime/pull/52154
将 TYP_FLOAT 传递给 gtNewDconNode 而不是创建新Scope https://github.com/dotnet/runtime/pull/51928
感谢@SingleAccretion的这些贡献。
动态 PGO https://github.com/dotnet/runtime/issues/43618
修改内联规模计算 https://github.com/dotnet/runtime/pull/51593
使用排除块检查更新 optReachable https://github.com/dotnet/runtime/pull/51842
概括围绕空流优化的分支 https://github.com/dotnet/runtime/pull/51409
为新的 GetLikelyClass PGO 记录类型添加 MCS jitflags 支持 https://github.com/dotnet/runtime/pull/51578
在尾调用后概括检查有效 IR 以支持 crossgen2 确定性 https://github.com/dotnet/runtime/pull/51903
更通用的价值类去虚拟化 https://github.com/dotnet/runtime/pull/52210
链式保护去虚拟化 https://github.com/dotnet/runtime/pull/51890


JIT 循环优化https://github.com/dotnet/runtime/issues/43549
改进的循环反转在 BenchE 中显示出良好的性能提升 https://github.com/dotnet/runtime/pull/52347<img src=”https://user-images.githubusercontent.com/63486087/121261311-6d8bd780-c867-11eb -896e-922725a5fd17.png” 宽度=”600″ 高度=”120″>
缩放克隆循环块权重 https://github.com/dotnet/runtime/pull/51901
在循环克隆期间不要重新计算 preds 列表以保留边缘上的现有配置文件数据 https://github.com/dotnet/runtime/pull/51757
改进 DOT 流图转储 https://github.com/dotnet/runtime/pull/52329
改进循环展开文档 https://github.com/dotnet/runtime/pull/52099
LSRA https://github.com/dotnet/runtime/issues/43318
在“分配寄存器”表中包含寄存器选择启发式 https://github.com/dotnet/runtime/pull/52513 新旧表的差异:

保持结构体在寄存器 https://github.com/dotnet/runtime/issues/43867
为寄存器中的结构准备 JIT 后端 https://github.com/dotnet/runtime/pull/52039
struct enreg 的活性修复 https://github.com/dotnet/runtime/pull/51851
改进结构初始化以将 ASG struct(LCL_VAR, 0) 保持为 STORE_LCL_VAR struct(0) https://github.com/dotnet/runtime/pull/52292
优化调试经验
为 nint/nuint 识别和处理 Vector64/128/256 https://github.com/dotnet/runtime/pull/52016
添加 clrjit.natvis 文件以获得更好的调试体验 https://github.com/dotnet/runtime/pull/52668 jitstd::list 的示例可视化工具以及 RefPosition 和内部 registerAssignment 的分解以显示所有寄存器:

SIMD
涉及 SIMD 或 HWIintrinsics 的某些方法的内联现在应该具有改进的代码生成和性能。我们看到了高达 95% 的改进。

结束语
就功能的广度和数量而言,.NET 6 Preview 5 可能是迄今为止最大的预览版。您可以使用源生成器和分析器查看 Roslyn 功能对底层库功能的影响程度。未来真的到来了。我们现在拥有一个非常强大的编译器工具链,使我们能够生成高度优化和正确的代码,并为您自己的项目提供完全相同的体验。
现在是开始测试 .NET 6 的好时机。现在我们根据您的反馈采取行动还有足够的时间。很难想象,虽然我们要到2021年11 月才会正式发布,但反馈窗口很快就会缩小到仅针对高严重性问题。团队提前进行了大约一大半的预览,并将很快转向主要关注质量问题。如果可以,请尝试 .NET 6。
感谢您成为 .NET 开发人员。




