上周,发布了.NET Core 3.0(预览版6) 。 它包括程序集编译更新,以改进启动,通过链接程序和EventPipe进行改进以优化应用程序大小。 我们还在ARM64上为Alpine发布了新的Docker映像。

WPF和Windows窗体更新
WPF团队已完成在GitHub上发布大多数WPF代码的过程 。 实际上,他们只是发布了15个版本的源代码 。 对于那些熟悉WPF的人来说,程序集名称应该非常熟悉。
在某些情况下,测试仍处于待办事项中,必须在3.0 GA或之前发布。 但是,所有这些代码的存在应该使WPF社区能够完全参与对WPF进行的更改。 在阅读了GitHub的一些问题之后,很明显,社区有您自己想要实现的新产品的积压。 您如何看待这个黑暗的话题?
高山Docker映像
Docker映像现在可用于ARM64上的.NET Core和ASP.NET Core。 以前,它们仅适用于x64。
可以在Dockerfile
或Dockerfile
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
事件管道增强
事件管道现在支持多会话。
添加了新的性能计数器:
- %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包进行交付。 我们希望获得有关此方案是否重要的更多反馈。
回溯到.NET Framework和NGEN ,AOT程序集的编译长期以来一直是.NET的概念。 NGEN的主要缺点是必须使用NGEN工具在客户端计算机上进行编译。 作为应用程序构建的一部分,无法生成NGEN映像。
现在是.NET Core。 它带有crossgen ,可以生成新的ReadyToRun格式的机器映像。 该名称描述了其核心价值,即这些计算机映像可以作为程序集的一部分创建,并且可以“运行”,而无需在客户端计算机上进行任何其他工作。 这是在应对气候变化方面的一项重大进步,也是一项重大胜利。
在兼容性方面,ReadyToRun映像类似于IL程序集,但有一些关键区别。
- IL程序集仅包含IL代码 。 它们可以在支持为此程序集指定的目标基础结构的任何运行时环境中工作。 例如,
netstandard2.0
构建可以在.NET Framework 4.6+和.NET Core 2.0+上,任何受支持的操作系统(Windows,macOS,Linux)和体系结构(Intel,ARM,32位,64位)上运行。 - R2R程序集包含IL和本机代码。 它们针对.NET Core运行时和运行时环境(RID)的特定最低版本进行了编译。 例如,可以对.NET Core 3.0和Linux x64进行R2R编译
netstandard2.0
构建。 因为它将包含只能在此运行时环境中使用的本机代码,所以它将仅在此配置或兼容配置中使用(例如,Linux x64上的.NET Core 3.1或.NET Core 5.0)。
使用说明
ReadyToRun编译仅可用于发布。 预览版在.NET Core 3.0(预览版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核心3.0 SDK附带了一个工具,该工具可以通过分析IL并消除未使用的内部版本来减小应用程序的大小。
使用.NET Core,您始终可以发布独立的应用程序,其中包括运行代码所需的一切,而无需在部署目标上安装.NET。 在某些情况下,该应用程序仅需要框架的一小部分,并且可以通过仅包含所使用的库来使其变得更小。
我们使用IL构建器来扫描您的应用程序的IL,以确定实际需要什么代码,然后排除未使用的框架库。 这可以显着减小某些应用程序的大小。 通常,小型控制台应用程序(如工具)会获得最大收益,因为它们经常使用框架的一小部分,并且通常很适合裁剪。
要使用此工具,请在项目中将PublishTrimmed=true
设置并发布独立的应用程序:
dotnet publish -r <rid> -c Release
发布输出将包括基础结构库的子集,具体取决于正在调用的应用程序代码。 对于helloworld应用程序,链接器将大小从〜68 MB减小到〜28 MB。
裁剪时使用反射或相关动态功能的应用程序或框架(包括ASP.NET Core和WPF)通常会中断,因为链接器不了解这种动态行为,并且通常无法确定运行时反射所需的框架类型。 要裁剪此类应用程序,您必须告诉链接器有关在代码以及您依赖的任何程序包或环境中进行反射所必需的任何类型。 裁剪后一定要测试您的应用程序。
有关IL Linker的更多信息,请参阅文档或访问mono / linker存储库。
注意:在.NET Core的早期版本中, ILLink.Tasks作为外部NuGet软件包提供,并提供了大多数相同的功能。 不再受支持-升级到最新版本3.0 SDK。
链接器和ReadToRun链接器共享
链接器链接器和ReadyToRun链接器可用于同一应用程序。 通常,链接器使您的应用程序更小,然后可以运行的编译器将其再次放大一些,但具有明显的性能提升。 值得测试各种配置以了解每个选项的效果。
注意: dotnet / sdk#3257防止WPF和Windows Forms应用程序共享链接器和ReadyToRun。 我们正在努力将其修复为.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") };
另外,默认情况下,您可以通过将DefaultRequestVersion
设置为HttpClient
来发送HTTP / 2请求。
var client = new HttpClient() { BaseAddress = new Uri("https://localhost:5001"), DefaultRequestVersion = new Version(2, 0) };
由于此更改,服务器和客户端必须就所使用的协议版本达成一致。 ALPN(应用层协议协商)是TLS扩展,允许服务器和客户端协商用作其交互的一部分的协议版本。 但是,请记住,大多数服务器仅支持将ALPN作为建立HTTP / 2连接的唯一方法。 因此,HTTP / 2仅由HttpClient
通过TLS连接协商。
在开发方案中,当服务器和客户端先验地知道它们都将使用不加密的HTTP / 2时,可以通过设置AppContext
开关或环境变量来通过明文建立HTTP / 2连接。 ( DOTNET_SYSTEM_NET_HTTP_SOCKETSHTTPHANDLER_HTTP2UNENCRYPTEDSUPPORT=1
)。
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
完成时间
如果您尝试新功能,我们将非常高兴。 请报告发现的问题或错误。 您也可以提交对新功能的请求,但是它们的实现必须等到下一个版本发布。
现在,我们非常接近完成.NET Core 3.0组件的工作,现在,我们正在将团队的注意力转移到提高发布质量上。 我们距离错误修复和性能改进还有几个月的时间。
顺便说一下,对于下一个主要更新,我们将切换.NET Core存储库中的master
分支。 最有可能在7月的Preview 7之后立即发生。
感谢您测试.NET Core 3.0。 感谢您的帮助。 目前,我们致力于使最终版本成为您最有趣,最优质的版本。