很快乐.NET 6 预览版5终于跟大家见面了。咱们当初正处于.NET 6 的后半局部,开始整合一些重要的性能。 例如.NET SDK 工作负载,它是咱们.NET 对立愿景的根底,能够反对更多类型的应用程序。 与其余性能一样,它也是为了更好地服务于端到端的用户体验。

您能够下载实用于Linux、macOS 和Windows 的.NET 6 预览版5。

  • 安装程序和二进制文件
  • 容器镜像
  • Linux 软件包
  • 发行阐明
  • API差别
  • 已知的问题
  • GitHub 问题跟踪器

请参阅ASP.NET Core、EF Core以及.NET MAUI,理解无关Web、数据拜访和跨平台UI 计划新增性能的更多详细信息。

Visual Studio 2022 预览版1 也在明天公布,.NET 6 预览版5蕴含其中。.NET 6 还在Visual Studio 16.11和Visual Studio for Mac 8.9进行了测试。 如果您想在Visual Studio中试用.NET 6,咱们建议您应用这些版本。

您也能够查看新的对话帖,深刻理解工程师们对.NET新性能的想法。

.NET SDK:可选的工作负载改良

SDK 工作负载是一项新的.NET SDK 性能,它使咱们可能在不减少SDK 大小的状况下增加对新应用程序类型(如挪动和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 增加更多分析器。

默认状况下,大多数新分析器利用在Info级别。您能够通过如下AnalysisMode的配置在Warning级别启用这些分析器:

\<AnalysisMode\>AllEnabledByDefault\</AnalysisMode\>

咱们公布了咱们想要的.NET 6 分析器集(加上一些额定的货色),而后将其中的大部分都公开了。

预览版5 中蕴含了Newell Clark和Meik Tranel的以下实现。请留神,社区用户在之前的预览版中奉献了其余实现。

ContributorIssueTitle
Newell Clarkdotnet/runtime #33777Use span-based string.Concat
Newell Clarkdotnet/runtime #33784Prefer string.AsSpan() over string.Substring() when parsing
Newell Clarkdotnet/runtime #33789Override Stream.ReadAsync/WriteAsync
Newell Clarkdotnet/runtime #35343Replace Dictionary\<,\>.Keys.Contains with ContainsKey
Newell Clarkdotnet/runtime #45552Use String.Equals instead of String.Compare
Meik Traneldotnet/runtime #47180Use String.Contains(char) instead of 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 为应用程序设置默认字体。 您应用的模式相似于设置high dpi或视觉款式。

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 带来了很大的妨碍。 默认字体设置使为应用程序抉择所需字体变得简略,打消了迁徙的阻碍。

库:放弃对旧框架的反对

从包中删除框架是一个毁坏源代码的改变。然而,让它始终反对咱们公布的所有框架也减少了包的复杂性和大小。过来,咱们通过_harvesting_来解决这个问题,也就是:

  • 咱们只为"以后"反对的框架做构建
  • 在构建期间,咱们下载包的晚期版本,并切除咱们不再构建的晚期框架的二进制文件

尽管这意味着您能够随时更新而不用放心咱们会删除框架,但这也意味着如果您应用切割过的二进制文件,您将永远不会取得任何谬误修复或新性能。换句话说,切割过的无奈提供服务的资产,当初曾经被暗藏了,因为从您的角度来看,您能够持续将包更新到更高版本,即便您正在应用咱们不再更新的旧二进制文件。

从.NET 6 Preview 5 开始,咱们打算不再执行任何模式的harvesting,以确保咱们为交付的所有内容都失去更好的服务。这意味着咱们将放弃对任何早于以下版本的反对:

  • .NET Framework 4.6.1
  • .NET Core 3.1
  • .NET Standard 2.0

如果您以后正在援用来自晚期框架的受影响的包,您将无奈再将援用的包更新到更高版本。您能够将您的我的项目从新指向到更高版本的框架或抉择不更新援用的包(这通常不是一个大的回退,因为无论如何您曾经在应用解冻的二进制文件)。

更多详细信息,包含受影响软件包的残缺列表,请参阅dotnet/announcement:删除旧框架版本。

库:Microsoft.Extensions

咱们始终在改良此版本的Microsoft.Extensions API。 在预览版5 中,咱们专一于托管和依赖注入。 在预览版4 中,咱们增加了一个用于日志记录的编译时源生成器。

感激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();

在预览版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 InvalidOperationExceptionusing (var scope = provider.CreateScope()){    var foo = scope.ServiceProvider.GetRequiredService<Foo>();}class Foo : IAsyncDisposable{    public ValueTask DisposeAsync() => default;}

您能够通过将返回的scope强制转换为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.Json 中引入了一个新的源码生成器。JSON 源码生成器与JsonSerializer 协同工作,并且能够配置成多种多样的工作形式。是否应用新的源码生成器由您决定。它能够提供以下益处:

  • 缩小启动工夫
  • 进步序列化吞吐量
  • 缩小公有内存应用
  • 移除运行时System.Reflection 和System.Reflection.Emit 的应用
  • 容许兼容trim的JSON 序列化

例如,源码生成器能够生成对properties更简略无效的赋值/取值的代码,而不是在运行时通过Reflection.Emit生成get和set办法(这会用到公有内存并且影响启动速度),使得性能失去了更大的进步。

您能够应用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    {    }}

咱们通过JsonSerializerOptionsAttribute 定义了一组JsonSerializer 性能,这些性能由提供最佳序列化吞吐量的源码生成模式提供。 这些性能能够提前指定给源码生成器,以防止在运行时进行额定查看。 如果该属性未声明,运行时会应用默认的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\&lt;T\&gt; — 第二个应用更通用的无类型化实现,该实现执行类型测试以确定上下文实例中是否存在类型化实现。因而,它有点慢(因为类型测试)。如果给定类型没有源码生成的实现,则序列化程序会抛出NotSupportedException。然而它不会回退到基于反射的实现(咱们的设计明确了这一点)。

基于Utf8JsonWriter的最快、最优化的源码生成模式目前仅可用于序列化。咱们会依据您的反馈决定是否在将来提供基于Utf8JsonReader的反序列化实现。

然而,源码生成器还提供类型元数据初始化逻辑,这也有助于反序列化。要应用事后生成的类型元数据反序列化JsonMessage 的实例,您能够执行以下操作:

JsonSerializer.Deserialize(json, JsonContext.Default.JsonMessage);

相似于下面的序列化,你也能够这样写:

JsonSerializer.Deserialize(json, typeof(JsonMessage), JsonContext.Default);

补充笔记

  • 能够通过派生的局部JsonSerializerContext 实例上的[JsonSerializable] 蕴含多种类型以用于源生成,不止反对一个。
  • 源生成器还反对嵌套对象和汇合成员,而不仅仅是原始类型。

库:WebSocket 压缩

压缩对于通过网络传输的任何数据都很重要。WebSockets 当初启用压缩。咱们应用了WebSockets 的permessage-deflate 扩大实现,RFC 7692。它容许应用DEFLATE 算法压缩WebSockets 音讯无效负载。

此性能是用户对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,这些API 减少了对Metrics 可察看性场景的反对。

库测量记录示例

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\&lt;T\&gt; 当初反对nint 和nuint

Vector\&lt;T\&gt; 当初反对在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 集成并将更多本地运行时事件(Microsoft-Windows-DotNETRuntime) 适配到MonoVM 中,从而在nettrace 文件中启用更多事件。

现已具备以下性能:

  • 在MonoVM 和CoreCLR 之间共享本机EventPipe/DiagnosticsServer 库。
  • 将TCP/IP 反对增加到DiagnosticsServer 并利用该配置构建MonoVM iOS/Android 运行时包。须要以反对挪动平台。
  • BCL EventSources 在MonoVM 上运行,将事件发送到EventPipe。
  • System.Diagnostics.Tracing.RuntimeEventSource 收回的BCL 运行时计数器连贯到MonoVM,可从dotnet-counters 等工具耗费。
  • 自定义事件源在MonoVM 上运行,将自定义事件发送到EventPipe,可通过dotnet-trace 等工具应用。
  • 自定义事件计数器在MonoVM 上运行,将自定义计数器事件发送到EventPipe,可通过dotnet-counters 等工具应用。
  • 示例分析器在MonoVM 上实现,将事件发送到EventPipe。开启了应用dotnet-trace 在MonoVM 上进行CPU 剖析的能力。
  • dotnet-dsrouter 诊断工具的实现,容许应用现有的诊断工具,如dotnet-trace、dotnet-counters、dotnet-stack 以及在挪动指标上运行的MonoVM,无需更改现有工具。dotnet-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 而不是创立新范畴 https://github.com/dotnet/runtime/pull/51928

感激@SingleAccretion的这些奉献。

动静PGO

  • 批改内联规模计算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 循环优化

  • 改良的循环反转在BenchE 中显示出良好的性能晋升 https://github.com/dotnet/run...\&lt;img src="https://user-images.githubuse...; width="600″ height="120″\&gt;
  • 缩放克隆循环块权重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/pull/52513新旧表的差别:

放弃构造在注册

  • 为寄存器中的构造筹备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 预览版5 可能是迄今为止最大的预览版。 您能够应用源生成器和分析器查看Roslyn 性能对低级库性能的影响水平。 将来真的到来了。 咱们当初领有一个十分弱小的编译器工具链,使咱们可能生成高度优化和正确的代码,并为您本人的我的项目提供完全相同的体验。

当初是开始测试.NET 6 的好时机。当初咱们依据您的反馈采取行动还为时过早。 很难设想,尽管咱们要到2021 年11 月才会公布,但反馈窗口很快就会放大到仅针对高严重性问题。 该团队提前进行了大概一年半的预览,并将很快转向次要关注品质问题。 如果能够,请尝试.NET 6。

感谢您成为.NET 开发人员。

本文由博客一文多发平台 OpenWrite 公布!