很高兴地宣布,我们发布了.NET 7 预览版3。.NET 7的第三个预览版包括了对可观察性、启动时间、codegen、GC regions、本地AOT编译等方面的增强。您现在就可以获取并开始尝试新功能,包括:
- 原生 AOT
- 默认 GC regions
- ASP.NET Core 启动时间改进
您可以下载适用于 Windows、macOS 和 Linux 的 .NET 7 预览版 3。
.NET 7预览版3已经在Visual Studio 17.2预览版3中进行了测试。如果您想尝试 .NET 7和Visual Studio的系列产品,我们建议您使用预览版。Mac版的Visual Studio暂时还未支持.NET 7预览版,但很快就会发布。现在,让我们了解这个版本中的一些最新更新的内容。
更快、更轻量级的原生AOT应用
在.NET 7 预览版2的博客文章中,我们宣布原生AOT项目已经从实验状态转移到.NET /runtime repo的.NET 7的主线开发中。我们知道您们中的许多人都在急切地等待着来自团队的关于Native AOT的更新,我们在预览版3中有一些新的更新。
如果您想了解原生AOT的详细信息,或者想要开始使用它,repo文档是最好的选择。
我们也意识到您们中的一些人可能不熟悉原生 AOT是什么,所以我们想分享它的一个快速概述给您们。
▌什么是原生AOT?
提前编译(AOT)是指在应用程序构建时(而不是运行时)生成代码的一系列技术。AOT 对 .NET 来说并不陌生。今天我们发布了用于客户端和服务器场景的ReadyToRun,以及用于移动和WASM的Mono AOT。原生AOT为.NET桌面客户端和服务器场景带来了完整的原生预编译。原生AOT并没有取代这些现有技术,而是提供了一组新的功能,可以解锁新的form factors。
现有的AOT编译的.NET程序集包含特定于平台的数据结构和本地代码,用于通常在运行时完成的前置加载工作。预编译这些工件可以节省启动时的时间(例如ReadyToRun),并允许访问非JIT平台(例如iOS)。如果没法做预先编译,.NET要么退回到JIT,要么退回到解释(取决于平台)。
原生AOT类似于.NET现有的AOT技术,但它只生成原生artifacts。事实上,本机AOT运行时并不知道如何读取 .NET程序集文件格式—所有这些都是平台本机的。可执行文件格式解析完全由底层操作系统处理。
原生AOT的主要优点是在启动时间、内存使用、访问受限平台(不允许JIT)和更小的磁盘大小方面。当操作系统将应用程序中的页面放入内存时,应用程序就开始运行。数据结构是为了运行AOT生成的代码而优化的,而不是为了在运行时编译新代码。这类似于Go、Swift和Rust等语言的编译方式。原生AOT最适合哪些非常看重启动时间的环境。针对原生AOT的要求比一般的.NET Core/5+应用程序和库更严格。原生AOT禁止在运行时emit新代码(例如Reflection.Emit),也禁止在运行时加载新的 .NET程序集(例如插件模型)。
▌为原生AOT准备应用程序
对于.NET 7,我们将控制台应用和原生库作为原生AOT的主要场景。应用程序开发人员和库作者现在可以通过确保他们的应用程序是可调整的来利用原生AOT。由于剪裁是原生AOT编译的必要条件,现在就为剪裁准备应用程序和库将帮助它们为原生AOT做好准备。如果您是任何一个.NET库的作者,遵循“剪裁库”说明将帮助你为剪裁库和原生AOT做好准备。
我们计划在.NET 7中发布的一个使用原生AOT编译的应用是Crossgen工具。Crossgen是.NET SDK的一部分。CoreCLR AOT编译器生成ReadyToRun可执行文件。Crossgen是用c#编写的,我们目前将其编译后作为ReadyToRun应用发布。在编译速度和大小方面,我们已经看到了一些非常有前途的数字。Crossgen从原生AOT中获益良多,因为它是一个短暂的进程,启动开销主导了整个执行时间:
展望未来,原生AOT的兼容性将在.NET的下几个版本中得到改善,但是在许多情况下总有理由选择JIT。我们还将在dotnet SDK中为使用原生AOT发布项目添加更多的支持。
可观察性
.NET 7继续对云原生OpenTelemetry规范的支持。预览版3增加了对规范升级#988和#1708的支持,使采样器的跟踪状态可变。
// ActivityListener 采样回调
listener.Sample = (ref ActivityCreationOptions activityOptions) =>
{
activityOptions = activityOptions with { TraceState = "rojo=00f067aa0ba902b7" };
return ActivitySamplingResult.AllDataAndRecorded;
};
System.Composition.Hosting
最新的托管可扩展性框架进行了轻微的更新,以与以前版本的API保持一致。新的API允许向System.Composition.Hosting容器添加单个对象实例。类似于遗留接口System.ComponentModel.Composition.Hosting中提供的功能以及ComposeExportedValue(compostioncontainer, T)(https://aka.ms/exportedvalue)
建议:将现有对象注入MEF2
namespace System.Composition.Hosting
{
public class ContainerConfiguration{
public ContainerConfiguration WithExport(TExport exportedInstance);
public ContainerConfiguration WithExport(TExport exportedInstance, string contractName = null, IDictionary metadata = null);
public ContainerConfiguration WithExport(Type contractType, object exportedInstance);
public ContainerConfiguration WithExport(Type contractType, object exportedInstance, string contractName = null, IDictionary metadata = null);
}
}
启用Write-Xor-Execute后,启动时间得到了改善
性能仍然是.NET 7的主要关注点。dotnet/runtime#65738 PR重新实现了预编码和调用计数存根(分级编译助手存根),以显著减少运行时中可执行代码创建后修改的数量。这使得启动时间提高了10-15%。
另外,即使没有启用Write-Xor-Execute,这种变化也会在一些微基准和一些ASPNet基准中带来稳定状态的性能提升(最高达8%)。
然而,在即将发布的预览版本中,也会有一些由该更改导致的回归(没有启用Write-Xor-Execute)。这是在Orchard和fortune对英特尔处理器的基准测试结果里观察到的。
循环优化
• 对于System.Collections.Tests.Perf_BitArray. BitArrayLeftShift(尺寸:512), 循环克隆将单次调用的持续时间提高了21%。
一般优化
- 从隐藏缓冲区中返回的被调用对象中删除额外的结构体副本
https://github.com/dotnet/run... - 展开String.Equals和str.StartsWith表示常量字符串
https://github.com/dotnet/run... - 扩展Equals/StartsWith 为OrdinalIgnoreCase自动向量化
https://github.com/dotnet/run... - setcc之后的Movzx优化显示代码大小减少了0.03 ~ 0.16%
https://github.com/dotnet/run...
GC regions默认启用
在预览版 3中,默认情况下启用了region功能,该功能有助于提高高吞吐量应用程序的内存利用率。除了MacOS和原生AOT(将来会启用),该功能现在已在所有平台上启用。更多细节可以访问这个问题。
由于region最初的分配方式,我们预计较小的应用程序的工作集会增加。如果您注意到任何功能或性能差异,请在runtime repo中创建一个问题。
密码学:更好的生成X.500名称
通过引入一个类,可以更清晰地解析X.500名称,这一更改简化了处理证书的工作。
一般来说,任何想要构建X.500名称的人(比如用CertificateRequest类创建测试证书的人)都是通过字符串操作来实现的,要么是通过简单的文字,要么是通过字符串格式化,例如:
request = new CertificateRequest($"CN={subjectName},OU=Test,O=""Fabrikam, Inc.""", ...);
这通常没有问题,除非subjectName包含逗号、引号或任何对解析器有影响的内容。了解决这个问题,我们添加了x500 distishednamebuilder类。因为每个方法只对一个相对区别名(RDN)进行操作,所以解析过程中没有歧义。另外,由于RDN标识符得到了扩展,您不再需要猜测“CN”代表什么
(“Common Name”)。
X500DistinguishedNameBuilder nameBuilder = new();
nameBuilder.AddCommonName(subjectName);
nameBuilder.AddOrganizationalUnitName("Test");
nameBuilder.AddOrganizationName("Fabrikam, Inc.");
request = new CertificateRequest(nameBuilder.Build(), ...);
针对.NET 7
针对目标.NET 7,你需要在你的项目文件中使用.NET 7目标框架代号(TFM)。例如:
net7.0
请看完整的.NET 7 tfm集合,包括特定于操作的tfm。
- net7.0
- net7.0-android
- net7.0-ios
- net7.0-maccatalyst
- net7.0-macos
- net7.0-tvos
- net7.0-windows
我们希望从.NET 6升级到.NET 7应该很简单。欢迎告诉我们在使用.NET 7测试现有应用程序过程中发现的任何重大变化。
支持
.NET 7是一个当前版本,这意味着它将从发布之日起18个月内获得免费的支持和补丁。值得注意的是,所有版本的质量都是相同的。唯一的区别是支持的长度。有关.NET支持策略的更多信息,请参阅.NET和.NET Core官方支持策略。
重大的变化
通过阅读.NET 7文档中的重大的变化,你可以找到.NET 7中最新的重大变化的列表。它按区域和版本列出了重大的变更,并提供了详细解释的链接。
要查看有哪些重大的变化已经被提出来了,但是目前还是review阶段,请follow.NET重大变化的github issue。
路线图
.NET的发行版包括产品、库、运行时和工具,代表了微软内部和外部多个团队的协作。您可以通过阅读产品路线图来了解更多关于这些领域的信息:
- ASP.NET Core 7和Blazor路线图
https://github.com/dotnet/asp... - EF 7路线图
https://docs.microsoft.com/zh... - ML.NET
https://github.com/dotnet/mac... - .NET MAUI
https://github.com/dotnet/mau... - WinForms
https://github.com/dotnet/win... - WPF
https://github.com/dotnet/wpf... - NuGet
https://github.com/NuGet/Home... - Roslyn
- 运行时
https://github.com/dotnet/cor...
感谢您对.NET的所有支持和贡献。请尝试一下.NET 7预览版3,告诉我们您的想法!
.NET 7预览版3