如果您是.NET性能的粉丝,最近有很多好消息,例如.NET Core 2.1中的性能改进宣布.NET Core 2.1,但我们还有更多的好消息。分层编译是一项重要的新特性功能,我们可以作为预览供任何人试用,从.NET Core 2.1开始。在我们测试的许多场景中,应用程序启动更快,并且在稳定状态下运行得更快。一个在.NET Core 2.1上运行的项目,以及对环境变量或项目文件进行微不足道的更改以启用它。在本文的其余部分,我们将介绍它是什么,如何使用它,以及为什么它是2.1版本的隐藏技能!

什么是分层编译?

从.NET Framework开始,代码中的每个方法通常都编译一次。但是,在决定如何进行会影响应用程序性能的编译时,需要进行权衡。例如,JIT可以进行非常积极的优化并获得很好的稳定性能,但是优化代码并不是一件容易的事情,因此您的应用程序启动速度非常慢。或者JIT可以使用非常简单的编译算法,这些算法可以快速运行,因此您的应用程序可以快速启动,但代码质量会更差,并且应用程序吞吐量会受到影响。.NET一直试图采用一种平衡的方法,在启动和稳定性能方面做得很合理,但使用单一编译意味着需要妥协。

分层编译功能通过允许运行时热交换技术对.NET进行多次编译同一个方法改变了以上前提。两套机制的分离以便我们可以选择最适合启动的技术,选择最稳定状态并且在两者上都表现出更好性能的第二种技术(分层编译)。在.NET Core 2.1中,这就是Tiered Compilation旨在为您的应用程序做的事情:

  • 更快的应用程序启动时间 - 当应用程序启动时,它会等待一些MSIL代码到JIT。分层编译要求JIT快速生成初始编译,如果需要,牺牲代码质量优化。之后,如果频繁调用该方法,则在后台线程上生成更优化的代码,并替换初始代码以保持应用程序的稳定性能。
  • 更快的稳定状态下的性能 - 对于典型的.NET Core应用程序,大多数框架代码将从预编译(ReadyToRun)映像加载。这对于启动非常有用,但预编译的映像具有版本控制约束和禁止某些类型优化的CPU指令约束。对于经常调用的这些镜像中的任何方法,分层编译请求JIT在后台线程上创建优化代码,以替换预编译版本。

更快?到底有多快?

我们将此作为预览版发布的部分原因是要了解它对您的应用程序的执行情况,但以下是我们对其进行测试的一些示例。虽然非常依赖于场景,但我们希望这些结果是您在类似工作场景上的典型代表,并且随着功能的成熟,结果将继续改进。基准测试是在默认配置下运行的.NET Core 2.1 RTM,并且所有数字都经过缩放,因此基准始终为1.0。在第一组中,我们有几个Tech Empower测试和MusicStore(用来专门测试的项目),这是我们常用的ASP.NET应用示例。

虽然我们的一些ASP.NET基准测试得益于特别好(MvcPlaintext RPS超过60% - 哇!),但分层编译并不特定于ASP.NET。以下是您在日常开发中可能遇到的一些示例.NET Core命令行应用程序:

你的应用程序将如何运作?测量比预测要容易得多,但我们可以提供一些广泛的经验法则。

  1. 启动改进主要适用于减少管理托管代码的时间。您可以使用PerfView工具来确定您的应用花费多少时间。在我们的测试中,jitting花费的时间通常会减少约35%。
  2. 稳定状态的改进主要适用于CPU绑定的应用程序,其中一些热代码来自.NET或ASP.NET预编译库。例如PerfView可以帮助您确定您的应用程序是这一类。

尝试一下

一个小免责声明,该功能仍然是一个预览。我们已对其进行了大量测试,但默认情况下未启用此功能,因为我们希望收集反馈并继续进行调整。打开它可能不会使你的应用程序更快,或者你可能遇到我们没有覆盖到的地方。如果遇到问题,微软随时为您提供帮助,您可以随时轻松将其禁用。如果您愿意,可以在生产中启用此功能,但我们强烈建议您事先进行测试。

有几种方式可以选择加入此功能,所有这些方法都具有相同的效果:

  • 如果使用.NET 2.1 SDK 自行构建应用程序 - 将MSBuild属性<TieredCompilation> true </ TieredCompilation>添加到项目文件中的默认属性组。例如:

GitHub 链接可找到以下代码

<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
<TieredCompilation>true</TieredCompilation>
</PropertyGroup>
</Project>
  • 如果运行已构建的应用程序,请编辑runtimeconfig.json以将System.Runtime.TieredCompilation = true添加到configProperties。例如:
  {
"runtimeOptions": {
"configProperties": {
"System.Runtime.TieredCompilation": true
}
},
"framework": {
...
}
}
  • 如果您想运行应用程序但不想修改任何文件,请设置环境变量
COMPlus_TieredCompilation=

有关尝试和测量性能的更多详细信息,请查看分层编译演示

获得这个技术

好奇它是如何工作的?不要害怕,理解这些内部细节不是使用分层编译所必需的,如果您愿意,可以跳过本节。一目了然,该功能可分为四个不同的部分:

  • JIT编译器可以配置为生成不同质量的汇编代码 - 令许多人惊讶的是,到目前为止,这还不是该功能的重点。回到.NET的起始,JIT支持默认编译模式和用于调试的无优化编译模式。正常模式产生更好的代码质量并且编译需要更长时间,而“无优化”模式则相反。对于分层编译,我们创建了新的配置名称“Tier0”和“Tier1”,但这些配置生成的代码与我们一直使用的“无优化”和“正常”模式大致相同。到目前为止,大多数JIT更改都涉及在请求“Tier0”代码时使JIT生成代码更快。我们希望将来继续提高Tier0编译速度,
  • CodeVersionManager(代码版本管理)跟踪同一方法的不同代码编译(版本) - 最基本的是一个大内存字典,它存储应用程序中.NET方法之间的映射和不同程序集实现的列表运行时可以使用它来执行该方法。我们使用一些技巧来优化这种数据结构,但如果你想深入研究项目的这个方面,可以参考我们提供的非常好的规范
  • 相同方法的不同汇编代码汇编之间,在运行时状态下热更新的机制, - 当方法A调用方法B时,调用将依赖于jmp指令。通过调整运行时的jmp指令可以控制执行B的哪个实现。
  • 决定要创建哪些代码版本以及何时在它们之间切换的策略 - 运行时始终首先创建Tier0,这是从ReadyToRun映像加载的代码,或者是使用最小化优化的代码。呼叫计数器用于确定频繁运行哪些方法,并使用计时器来避免在启动期间过早创建Tier1的工作。一旦计数器和计时器都满足,该方法就会排队,后台线程会编译Tier1版本。有关详细信息,请查看规范

我们从哪里开始?

分层编译创造了各种可能性,我们可以继续充分利用未来的时间。既然运行时可以利用更极端的情况,那我们就有了扩展边界的动力,既可以加快编译速度,又可以生成更高质量的代码。通过代码的运行时热更新,.NET可以进行更详细的分析,然后使用运行时反馈来进行更好的优化(配置文件引导优化)。这些技术可以允许代码生成器甚至超出无法访问配置文件数据的最佳静态优化器。或者还有其他选项,例如用于更好诊断的动态去优化,用于减少内存使用的可收集代码,以及用于性能检测或服务的热补丁。目前,我们最直接的目标仍然接近实际 - 确保预览中的功能运行良好,响应您的反馈,并完成工作的第一次迭代。

总结

我们希望Tiered Compilation为您的应用程序提供与我们的基准测试相同的重大改进,并且我们知道还有更多尚未开发的潜力。请试一试,然后访问github,向我们提供反馈,讨论,提问,甚至可以贡献一些自己的代码。谢谢!

原文:.NET Core 2.1中的分层编译(预览)

.NET Core 2.1中的分层编译(预览)的更多相关文章

  1. angular中封装fancyBox(图片预览)

    首先在官网下载最新版的fancyBox(一定要去最新网站,以前依赖的jquery版本偏低),附上链接:http://fancyapps.com/fancybox/3/ 然后在项目中引用jquery,然 ...

  2. Power BI中的QA功能预览

    微软在休斯敦的全球合作伙伴大会上发布了Power BI for Office 365,通过Excel和Office 365中的自服务式商业智能解决方案为信息工作者提供了数据分析以及可视化功能以帮助他们 ...

  3. 在Vue项目中 选择图片并预览

    最近开始使用vue做项目 在这个过程中,碰到了大多数做前端肯定经历的一个问题,就是文件上传预览 花了点时间解决,因此分享一下预览功能的解决方案 页面: <div class="sele ...

  4. vue项目中编写一个图片预览的公用组件

    今天产品提出了一个查看影像的功能需求. 在查看单据的列表中,有一列是影像字段,一开始根据单据号调用接口查看是否有图片附件,如果有则弹出一个全屏的弹出层,如果没有给出提示.而且,从列表进入详情之后,附件 ...

  5. 在 vue 中使用 vieiwer 图片预览插件

    https://blog.csdn.net/WestLonly/article/details/79801800?utm_source=blogxgwz0 首先,感谢原作者 官网链接 github地址 ...

  6. Sublime Text3 实现在浏览器中以HTML格式预览md文件

    1.首先找到Package Control 打开Sublime Text3,找到菜单栏:Preferences → Package Control,没有找到Package Control,那么点击Pa ...

  7. Android开发 获取视频中的信息(例如预览图或视频时长) MediaMetadataRetriever媒体元数据检索器

    前言 在Android里获取视频的信息主要依靠MediaMetadataRetriever实现 获取最佳视频预览图 所谓的最佳就是MediaMetadataRetriever自己计算的 /** * 获 ...

  8. JS中FireFox新开窗口预览打印处理的方式

    仅提供思路,勿喷如下↓ /** * 打印方法 * @param dom 要被打印的dom元素 * @param parentClassName 该组件的页面根组件class名 * @param pag ...

  9. Ext中图片上传预览的问题,困扰了好几天终于解决了,记录下

    { columnWidth:.50, xtype:'textfield', style:"padding-top:5px", name:'goodsMainPhoto', id:' ...

随机推荐

  1. mac 全角/半角标点符号切换

    快捷键:option+shift+H 背景是这样的,前段时间sublimeText新装了HTML/CSS/JS Prittify,JS代码格式化的快捷键是:command+shift+H. 记性有点差 ...

  2. ORACLE中内部函数SYS_OP_C2C和隐式类型转换

    什么是SYS_OP_C2C呢?官方的介绍如下: SYS_OP_C2C is an internal function which does an implicit conversion of varc ...

  3. ORACLE Index Lookup索引访问路径总结

    在ORACLE中,索引访问/查找(Index Lookup)路径有五种方式,分别为INDEX UNIQUE SCAN.INDEX RANGE SCAN.INDEX FULL SCAN.INDEX FA ...

  4. MyBatis笔记----mybatis分页

    mybatis版本3.4以下 结构 spring-mvc.xml <?xml version="1.0" encoding="UTF-8"?> &l ...

  5. 关于getdate()的不同的日期格式

    在使用Sql Server查询数据库时,我们经常会需要查询日期格式的数据,对于日期在sql语言中的格式有一定的要求,通过修改convert中的最后一位参数,可以返回不通格式的时间,具体实现如下: Se ...

  6. CVE-2017-8464 分析

    目录 CVE-2017-8464(stuxnet 3.0) 分析 0xFF 前言 0x00 分析工具 0x01 漏洞复现 1).生成一个DLL用于测试 2).构造一个恶意的lnk二进制文件 3).RU ...

  7. Visio画图--我的形状

    本人用的Visio 2013 打开Visio后新建一个拓扑图,发现左侧形状一栏不见了 形状栏可以保存很多自定义图形,怎么才能将形状一栏重新显示出来呢?方法其实很简单,方法如下所示: 这时候我们就会发现 ...

  8. spring cloud 微服务日志跟踪 sleuth logback elk 整合

    看过我之前的文章的就可以一步一步搭建起日志传输到搜索引擎 不知道的 看下之前的文章 (1) 记一次logback传输日志到logstash根据自定义设置动态创建ElasticSearch索引 (2)关 ...

  9. 一个tomcat部署多个应用实例

    安装JDK7sudo apt-get install java7-jdk 安装tomcat7 Tomcat7下载地址http://mirror.bjtu.edu.cn/apache/tomcat/to ...

  10. 修改mysql默认端口

    最初,我将mysql端口改成了3307,现在需要将其改3306端口,已改好,做个记录 首先:借助资源监视器,找到对应的端口,查看对应的Pid,然后打开任务管理器,点击服务,找到对应的服务器,将其服务停 ...