很快乐.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 的以下实现。请留神,社区用户在之前的预览版中奉献了其余实现。
Contributor | Issue | Title |
---|---|---|
Newell Clark | dotnet/runtime #33777 | Use span-based string.Concat |
Newell Clark | dotnet/runtime #33784 | Prefer string.AsSpan() over string.Substring() when parsing |
Newell Clark | dotnet/runtime #33789 | Override Stream.ReadAsync/WriteAsync |
Newell Clark | dotnet/runtime #35343 | Replace Dictionary\<,\>.Keys.Contains with ContainsKey |
Newell Clark | dotnet/runtime #45552 | Use String.Equals instead of String.Compare |
Meik Tranel | dotnet/runtime #47180 | Use 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 InvalidOperationException
using (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\<T\> — 第二个应用更通用的无类型化实现,该实现执行类型测试以确定上下文实例中是否存在类型化实现。因而,它有点慢(因为类型测试)。如果给定类型没有源码生成的实现,则序列化程序会抛出 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\<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 集成并将更多本地运行时事件(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…\<img src=”https://user-images.githubuse…; width=”600″ height=”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/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 公布!