宣布.NET Core 3.0预览版6

今天,我们宣布.NET Core 3.0 Preview 6 。 它包括编译程序集的更新,以改进启动,通过链接程序和EventPipe的改进来优化应用程序的大小。 我们还在ARM64上发布了用于Alpine的新Docker映像。





WPF和Windows窗体更新


WPF团队现在已经完成了将大部分WPF代码库发布到GitHub的工作 。 实际上,他们只是发布了15个程序集的源代码 。 对于熟悉WPF的任何人,程序集名称都应该非常熟悉。


在某些情况下,测试仍在积压中以在3.0 GA或之前发布。 也就是说,所有这些代码的存在应该使WPF社区能够完全参与WPF的更改。 从阅读GitHub的一些问题可以明显看出,社区有自己的积压已在等待实现。 黑暗的主题,也许吗?


高山码头工人图像


Docker映像现在可用于ARM64上的.NET Core和ASP.NET Core。 它们以前仅适用于x64。


可以在DockerfileDockerfile docker pull使用以下图像,如下所示:


  • docker pull mcr.microsoft.com/dotnet/core/runtime:3.0-alpine-arm64v8
  • docker pull mcr.microsoft.com/dotnet/core/aspnet:3.0-alpine-arm64v8

事件管道改进


事件管道现在支持多个会话。 这意味着您可以使用EventListener进程内消费事件,同时拥有进程外事件管道客户端。


添加了新的Perf计数器:


  • %GC时间
  • Gen 0堆大小
  • 第一代堆大小
  • 第2代堆大小
  • LOH堆大小
  • 分配率
  • 装配件数
  • 线程池线程数
  • 监视锁争用率
  • ThreadPool工作项队列
  • ThreadPool完成的工作项比率

现在,使用相同的事件管道基础结构来实现Profiler附加。


请参阅 David Fowler一起使用计数器来了解如何使用事件管道执行自己的性能调查或仅监视应用程序状态。


请参阅dotnet-counters以安装dotnet-counters工具。


使用ReadyToRun图像优化.NET Core应用


通过将应用程序程序集编译为ReadyToRun(R2R)格式,可以缩短.NET Core应用程序的启动时间。 R2R是一种提前(AOT)编译的形式。


R2R二进制文件通过减少应用程序加载时JIT需要完成的工作量来提高启动性能。 二进制文件包含与JIT将产生的代码相似的本机代码,从而在性能最重要时(启动时)使JIT有了一些假期。 R2R二进制文件较大,因为它们既包含中间语言(IL)代码(某些情况下仍然需要此代码),也包含相同代码的本机版本,以改善启动。


.NET Core 3.0支持R2R。 它不能与.NET Core的早期版本一起使用。


样本性能数据


以下是使用示例WPF应用程序收集的性能数字。 该应用程序被发布为自包含的,并且未使用程序集链接器(在本文后面介绍)。


仅IL的应用程序:


  • 启动时间:1.9秒
  • 内存使用量:69.1 MB
  • 应用大小:150 MB

使用ReadyToRun图像:


  • 启动时间:1.3秒。
  • 内存使用量:55.7 MB
  • 应用大小:156 MB

ReadyToRun映像,说明


您可以R2R编译库和应用程序二进制文件。 目前,只能将R2R库作为应用程序的一部分进行编译,而不能作为NuGet包进行交付。 我们希望获得有关该方案是否重要的​​更多反馈。


AOT编译程序集作为.NET的概念已经很长时间了,可以追溯到.NET Framework和NGEN 。 NGEN有一个主要缺点,那就是必须使用NGEN工具在客户端计算机上进行编译。 作为应用程序构建的一部分,不可能生成NGEN映像。


输入.NET Core。 它带有crossgen ,可生成称为ReadyToRun的较新格式的本机图像。 该名称描述了其主要的价值主张,即这些本机映像可以作为构建的一部分进行构建,并且可以“运行”,而无需在客户端计算机上进行任何其他工作。 这是一项重大进步,也是应对气候变化的重要胜利。


在兼容性方面,ReadyToRun映像类似于IL程序集,但有一些关键区别。


  • IL程序集仅包含IL代码 。 它们可以在支持该程序集的给定目标框架的任何运行时上运行。 例如, netstandard2.0程序集可以在任何受支持的操作系统(Windows,macOS,Linux)和体系结构(英特尔,ARM,32位,64位)上的.NET Framework 4.6+和.NET Core 2.0+上运行。
  • R2R程序集包含IL和本机代码。 它们针对特定的最低.NET Core运行时版本和运行时环境(RID)进行编译。 例如,一个netstandard2.0程序集可能是为.NET Core 3.0和Linux x64编译的R2R。 它仅在该配置或兼容配置中可用(例如Linux x64上的.NET Core 3.1或.NET Core 5.0),因为它包含仅在该运行时环境中可用的本机代码。

使用说明


ReadyToRun编译是仅发布的选择功能。 我们已经发布了.NET Core 3.0 Preview 5的预览版。


要启用ReadyToRun编译,您必须:


  • PublishReadyToRun属性设置为true
  • 使用显式RuntimeIdentifier发布。

注意:编译应用程序程序集时,生成的本机代码特定于平台和体系结构(这就是为什么在发布时必须指定有效的RuntimeIdentifier的原因)。


这是一个例子:


 <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp3.0</TargetFramework> <PublishReadyToRun>true</PublishReadyToRun> </PropertyGroup> </Project> 

并使用以下命令发布:


 dotnet publish -r win-x64 -c Release 

注意:也可以在项目文件中设置RuntimeIdentifier


注意:ReadyToRun当前仅受自包含应用程序支持。 在以后的预览中,将为依赖框架的应用程序启用它。


可以通过在项目PublishReadyToRunEmitSymbols属性设置为true来启用本机符号生成。 您无需生成用于调试目的的本机符号。 这些符号仅对概要分析有用。


SDK当前支持一种将某些程序集从编译成ReadyToRun映像中排除的方法。 对于某些组件确实不需要针对性能进行优化的情况,这可能很有用。 这可以帮助减小应用程序的大小。 对于ReadyToRun编译器无法编译某个程序集的情况,这也可能是一个有用的解决方法。 排除是使用PublishReadyToRunExclude项组完成的。 范例:


 <ItemGroup> <PublishReadyToRunExclude Include="FilenameOfAssemblyToExclude.dll" /> </ItemGroup> 

跨平台/架构编译


ReadyToRun编译器当前不支持交叉目标。 您需要在给定的目标上进行编译。 例如,如果您想要Windows x64的R2R映像,则需要在该环境上运行publish命令。


例外情况:


  • Windows x64可用于编译Windows ARM32,ARM64和x86映像。
  • Windows x86可用于编译Windows ARM32映像。
  • Linux x64可用于编译Linux ARM32和ARM64映像。

装配链接


.NET core 3.0 SDK附带了一个工具,该工具可以通过分析IL和修剪未使用的程序集来减小应用程序的大小。


使用.NET Core,始终可以发布包含运行代码所需的一切的自包含应用程序,而无需在部署目标上安装.NET。 在某些情况下,该应用仅需要框架的一小部分即可运行,并且可能仅包含所使用的库就可以变得更小。


我们使用IL链接器扫描应用程序的IL,以检测实际需要哪些代码,然后修剪未使用的框架库。 这可以大大减小某些应用程序的大小。 通常,类似于工具的小型控制台应用程序受益最大,因为它们倾向于使用框架的较小子集,并且通常更易于调整。


要使用此工具,请在项目中设置PublishTrimmed=true并发布一个独立的应用程序:


 dotnet publish -r <rid> -c Release 

根据应用程序代码的调用,发布输出将包括框架库的子集。 对于helloworld应用程序,链接器将大小从〜68MB减小到〜28MB。


修剪后使用反射或相关动态功能的应用程序或框架(包括ASP.NET Core和WPF)通常会中断,因为链接器不了解这种动态行为,并且通常无法确定反射所需的框架类型在运行时。 要修剪此类应用程序,您需要告诉链接器有关代码中以及依赖的任何包或框架中反射所需要的任何类型。 修剪后一定要测试您的应用程序。


有关IL链接器的更多信息,请参阅文档 ,或访问mono /链接器库。


注意:在.NET Core的早期版本中, ILLink.Tasks作为外部NuGet软件包提供,并提供了许多相同的功能。 不再受支持-请更新到最新的3.0 SDK并尝试新的体验!


一起使用链接器和ReadToRun


链接器和ReadyToRun编译器可用于同一应用程序。 通常,链接器使您的应用程序更小,然后可以运行的编译器将其再次放大,但在性能上有明显优势。 值得在各种配置中进行测试以了解每个选项的影响。


注意: dotnet / sdk#3257可防止将链接器和ReadyToRun一起用于WPF和Windows Forms应用程序。 我们正在努力将其修复为.NET Core 3.0版本的一部分。


本地托管样本


该团队最近发布了本机托管示例 。 它演示了在本机应用程序中托管.NET Core的最佳实践方法。


作为.NET Core 3.0的一部分,我们现在向.NET Core本机主机公开常规功能,该功能以前只能通过正式提供的.NET Core主机提供给.NET Core托管的应用程序。 该功能主要与程序集加载有关。 使用此功能应该可以更轻松地生成可以利用.NET Core完整功能集的本机主机。


HttpClient中的HTTP / 2支持


HTTP / 2是HTTP协议的主要修订版。 HTTP / 2的一些显着功能是支持标头压缩和同一连接上的完全多路复用的流。 尽管HTTP / 2保留了HTTP的语义(HTTP标头,方法等),但它与HTTP / 1.x相比,是如何在数据结构和通过网络发送方面有所变化。


HttpClient现在添加了对发出HTTP / 2请求的支持。 当默认设置为HTTP / 1.1时,您可以通过在HTTP请求消息中设置版本来选择使用HTTP / 2。


 var client = new HttpClient() { BaseAddress = new Uri("https://localhost:5001") }; // HTTP/1.1 request using (var response = await client.GetAsync("/")) { Console.WriteLine(response.Content); } // HTTP/2 request using (var request = new HttpRequestMessage(HttpMethod.Get, "/") { Version = new Version(2, 0) }) using (var response = await client.SendAsync(request)) { Console.WriteLine(response.Content); } 

另外,您可以通过在HttpClient上设置DefaultRequestVersion属性来默认发送HTTP / 2请求。


 var client = new HttpClient() { BaseAddress = new Uri("https://localhost:5001"), DefaultRequestVersion = new Version(2, 0) }; // Defaults to HTTP/2 using (var response = await client.GetAsync("/")) { Console.WriteLine(response.Content); } 

由于此框架更改,服务器和客户端需要协商使用的协议版本。 应用层协议协商(ALPN)是TLS扩展,它允许服务器和客户端协商用作其TLS握手一部分的协议版本。 尽管可能在服务器和客户端之间就协议有先验知识,但是大多数服务器仅支持将ALPN作为建立HTTP / 2连接的唯一方法。 因此,HTTP / 2仅由HttpClient在TLS连接上协商。


在开发场景中,当服务器和客户端具有先验知识,即双方都将讲未加密的HTTP / 2时,可以通过设置AppContext开关或环境变量( DOTNET_SYSTEM_NET_HTTP_SOCKETSHTTPHANDLER_HTTP2UNENCRYPTEDSUPPORT=1 )在明文上建立HTTP / 2连接。


 AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); 

闭幕


请尝试新功能。 请提出问题或发现的挑战或挑战。 我们需要反馈! 您也可以提交功能请求,但是此时它们可能需要等待实现,直到下一个版本。


现在,我们已经非常接近.NET Core 3.0的功能完善,并且正在将团队的重点转移到版本的质量上。 我们还有几个月的错误修复和性能工作。 我们也将在此过程中感谢您的反馈。


关于这一点,我们将很快将.NET Core存储库上的master分支切换到下一个主要版本,可能在Preview 7版本(7月)或之后不久。


感谢您试用.NET Core 3.0预览版。 感谢您的帮助。 在这一点上,我们专注于掌握最终版本。




理查德·兰德
.NET团队经理

Source: https://habr.com/ru/post/zh-CN456224/


All Articles