如果您是.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. (python)面向对象

    一.面向对象概述 要了解面向对象,就需要先了解面向过程的概念,那么什么是面向过程编程呢?最具代表性的就是C语言了,所谓面向过程编程就是在做一件事的时候,需要按步骤进行,第一步干什么,第二步干什么,这种 ...

  2. Spark WordCount 文档词频计数

    一.使用数据 Apache Spark is a fast and general-purpose cluster computing system.It provides high-level AP ...

  3. python第一百一十一天 --Django 6 model 的相关操作

    创建数据库,设计表结构和字段 使用 MySQLdb 来连接数据库,并编写数据访问层代码 业务逻辑层去调用数据访问层执行数据库操作 import MySQLdb def GetList(sql): db ...

  4. IPerf——网络测试工具介绍与源码解析(4)

    上篇随笔讲到了TCP模式下的客户端,接下来会讲一下TCP模式普通场景下的服务端,说普通场景则是暂时不考虑双向测试的可能,毕竟了解一项东西还是先从简单的情况下入手会快些. 对于服务端,并不是我们认为的直 ...

  5. JavaScript -- 时光流逝(五):js中的 Date 对象的方法

    JavaScript -- 知识点回顾篇(五):js中的 Date 对象的方法 Date 对象: 用于处理日期和时间. 1. Date对象的方法 <script type="text/ ...

  6. xshell的一些常用配置

    1  在xshell中鼠标滚轮和右键的快捷方式 利用鼠标滚轮和右键快速粘贴上面复制的内容 打开xshell的工具---选项-----键盘和鼠标 点击确定 回到xshell即可使用

  7. February 11th, 2018 Week 7th Sunday

    Grasp all, lose all. 欲尽得,必尽失. Not to be greedy and not to try to get everything. Our time, energy an ...

  8. 力扣算法题—069x的平方根

    实现 int sqrt(int x) 函数. 计算并返回 x 的平方根,其中 x 是非负整数. 由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去. 示例 1: 输入: 4 输出: 2 示例 ...

  9. DP h回文子串 LCS

    题目背景 IOI2000第一题 题目描述 回文词是一种对称的字符串.任意给定一个字符串,通过插入若干字符,都可以变成回文词.此题的任务是,求出将给定字符串变成回文词所需要插入的最少字符数. 比如 “A ...

  10. Java中String对象两种赋值方式的区别

    本文修改于:https://www.zhihu.com/question/29884421/answer/113785601 前言:在java中,String有两种赋值方式,第一种是通过“字面量”赋值 ...