.NET 5 中的隐藏特性
前言
双十一当天 .NET 5 正式发布带来了很多的新特性和改进,个人觉得非常香,并且花了 10 分钟时间就把自己的 4 个 .NET Core 3.1 的项目升级到了 .NET 5,堪称无痛。
但是,.NET 5 中还有一些没有正式公开的隐藏特性,那么现在就开始介绍吧。
Crossgen 2
Crossgen 2 とは
Crossgen 其实就是众所周知的 ReadyToRun 特性。该功能将你的程序集进行一定程度的 AOT 编译,然后在运行时跟踪热路径对一些方法进行带有更多优化的 JIT 编译,即分层编译,这使得程序集的加载速度大幅提高。
但是 .NET 5 其实带了 Crossgen 的下一个版本:Crossgen 2。
Crossgen 2 的代码几乎是从 CoreRT 继承而来,并在此基础上做了很大改进。CoreRT 可以对 .NET 程序集进行完全的原生优化编译,编译出来的东西就是完全 native 的,和 Go 的体验完全一致。
Crossgen 2 则使用了这套方法,将你的程序集在支持范围之内进行 Native AOT 编译,然后运行时直接加载启动,并根据运行情况再使用 JIT 编译器进行进一步的优化,是一种混合 AOT 策略。
为什么说在支持范围之内呢?因为 Native AOT 必然对动态加载和 Emit 等特性不友好,但是 Crossgen 2 对于这些地方则直接跳过,并且由于是混合 AOT 方案,运行时依然存留有 JIT,因此这些功能完全不会受到影响。
使用
使用方法很简单,在你发布程序的时候加命令行参数 /p:PublishReadyToRun=true /p:PublishReadyToRunUseCrossgen2=true 即可,例如:
dotnet publish -c Release -r win-x64 /p:PublishReadyToRun=true /p:PublishReadyToRunUseCrossgen2=true
注意
由于该功能尚未正式发布,并且存在一些已知的问题还没有解决,因此如果要使用的话建议对发布出的程序做好测试。
另外,.NET 6 将会用 Crossgen 2 代替现有的 Crossgen 1,追求稳定的话可以等到明年再用。
栈上替换
栈上替换とは
栈上替换,即 On Stack Replacement。这个特性允许在运行时,即使一个方法有活跃的栈帧也能直接替换实现。
因此对于分层 JIT 功能来说,这个特性就允许 JIT 将未经优化的代码直接切换成经过优化的代码,即使被切换的方法存在活跃栈帧也没问题。
使用
这是一个运行时特性,需要通过设置两个环境变量来开启:
bash:
export COMPlus_TC_QuickJitForLoops=1
export COMPlus_TC_OnStackReplacement=1
cmd:
set COMPlus_TC_QuickJitForLoops=1
set COMPlus_TC_OnStackReplacement=1
pwsh:
$env:COMPlus_TC_QuickJitForLoops = 1
$env:COMPlus_TC_OnStackReplacement = 1
注意
当前仅支持 x64,且目前处于实验性阶段。
更激进的发布裁剪
发布裁剪とは
发布裁剪可以在发布时将没有用到的代码裁剪掉,使得发布出去的程序体积大幅度减小。
但是 .NET 5 默认的裁剪行为是程序集粒度的,意味着会保留用到了的程序集,哪怕你只用了程序集中的一个方法,整个程序集也会被保留下来。
但是 .NET 5 提供了一种更为激进的裁剪方式,基于方法粒度进行裁剪。
开启这个特性之后,如果一个程序集只被调用了一个方法,那裁剪后将只会保留这一个方法,而不是保留整个程序集。
使用
使用方法很简单,只需要发布时附带命令行参数 /p:PublishTrimmed=true /p:TrimMode=true 即可,例如:
dotnet publish -c Release -r win-x64 /p:PublishTrimmed=true /p:TrimMode=true
如果因为动态加载需要保留一些方法、类型或者程序集的话,可以按照如下文章内的方法进行配置:
https://devblogs.microsoft.com/dotnet/customizing-trimming-in-net-core-5/
注意
由于这种方法较为激进,请确保发布后进行充分的测试,以免出现因为动态加载导致运行时找不到方法的问题。
实验性运行时
.NET 大量的新功能已经转移到专门的实验性运行时仓库进行开发了,例如:
- NativeAOT:基于 RyuJIT 的完全原生编译
- NativeAOT-LLVM:使用 LLVM 做代码生成的完全原生编译
- ManagedQuic:完全 C# 实现的 QUIC 协议
- Utf8String:UTF-8 字符串类型
- JsonCodeGen:使用代码生成器的 JSON
- s390x:.NET 在 s390x 架构的移植
- FreeBSD:.NET 在 FreeBSD 系统的移植
- MIPS64:.NET 在 MIPS64 架构的移植
- RegexSRM:基于微软研究院成果 Symbolic Regex Matcher 的正则表达式实现
- DllImportGenerator:用于自动生成 P/Invoke 接口的代码生成器
等等,欢迎前往实验仓库中对应分支进行试用和贡献代码:https://github.com/dotnet/runtimelab 。
另外,MIPS64 的移植工作由国内龙芯社区团队完成,并将在 .NET 6 并入官方主线,相关信息在 https://github.com/gsvm/loongson-dotnet 。
总结
.NET 5 有很多的没有公开宣布的特性,其中很多特性都非常棒,虽然没有正式发布的现阶段可能还存在一些问题,后期也可能会有较大的改动,但是感兴趣的读者不妨提前体验一波。
.NET 5 中的隐藏特性的更多相关文章
- Java语言中的面向对象特性总结
Java语言中的面向对象特性 (总结得不错) [课前思考] 1. 什么是对象?什么是类?什么是包?什么是接口?什么是内部类? 2. 面向对象编程的特性有哪三个?它们各自又有哪些特性? 3. 你知 ...
- 关于C# 中的Attribute 特性
关于C# 中的Attribute 特性 作者: 钢钢 来源: 博客园 发布时间: 2011-01-09 23:30 阅读: 13921 次 推荐: 12 原文链接 [收藏] 摘要:纠结地说 ...
- Java语言中的面向对象特性:封装、继承、多态,面向对象的基本思想(总结得不错)
Java语言中的面向对象特性(总结得不错) [课前思考] 1. 什么是对象?什么是类?什么是包?什么是接口?什么是内部类? 2. 面向对象编程的特性有哪三个?它们各自又有哪些特性? 3. 你知道jav ...
- DjVu、PDF中的隐藏文本
作者:马健邮箱:stronghorse_mj@hotmail.com发布:2012.06.11 目录一.背景二.DjVu中的隐藏文本三.PDF中的隐藏文本 一.背景 目前对于扫描电子文档,网上比较流行 ...
- ASP.NET 5与MVC 6中的新特性
差点忘了提一句,MVC 6中默认的渲染引擎Razor也将得到更新,以支持C# 6中的新语法.而Razor中的新特性还不只这一点. 在某些情况下,直接在Web页面中嵌入某些JSON数据的方式可能比向服务 ...
- PHP 5.4中的traits特性
Trait 是 PHP5. 中的新特性,是 PHP 多重继承的一种解决方案.例如,需要同时继承两个 Abstract Class, 这将会是件很麻烦的事情,Trait 就是为了解决这个问题. 简单使用 ...
- ASP.NET MVC4中的bundles特性引发服务器拒绝访问(403错误)
在ASP.NET MVC4中微软引入了bundles特性,这个特性可以将服务器端的多个Javascript或多个css文件捆绑在一起作为一个单一的URL地址供客户端浏览器调用,从而减少了页面上Http ...
- c++中的隐藏、重载、覆盖(重写)
转自c++中的隐藏.重载.覆盖(重写) 1 重载与覆盖 成员函数被重载的特征: (1)相同的范围(在同一个类中): (2)函数名字相同: (3)参数不同: (4)virtual关键字可有可无. 覆盖是 ...
- C++中名字隐藏,名字查找优先于类型检查
题目 C++中名字隐藏是什么? 解答 让我们通过一个例子来讲解C++中的名字隐藏.在C++中,如果一个类里有一个重载的方法, 你用另一个类去继承它并重写(覆盖)那个方法.你必须重写所有的重载方法, 否 ...
随机推荐
- 在阿里云上搭建私有GIT仓库
在阿里云上搭建私有GIT仓库 年轻人就得好好学习,不能这么颓废 最近做项目练练手,用到了github, 但是github访问速度是真的慢啊,下载项目,下载一天了.所以呢,我是个成熟的人了,只好自己搭建 ...
- golang常用库:配置文件解析库-viper使用
一.viper简介 viper 配置解析库,是由大神 Steve Francia 开发,他在google领导着 golang 的产品开发,他也是 gohugo.io 的创始人之一,命令行解析库 cob ...
- 题解:洛谷P1357 花园
题解:洛谷P1357 花园 Description 小 L 有一座环形花园,沿花园的顺时针方向,他把各个花圃编号为 \(1∼n\).花园 \(1\) 和 \(n\) 是相邻的. 他的环形花园每天都会换 ...
- pytest文档43-元数据使用(pytest-metadata)
前言 什么是元数据?元数据是关于数据的描述,存储着关于数据的信息,为人们更方便地检索信息提供了帮助. pytest 框架里面的元数据可以使用 pytest-metadata 插件实现.文档地址http ...
- 实时离线一体化在资产租赁saas服务中使用
流水查询需求 需求第一期: 基于TB级的在线数据,支持缴费帐单明细在线查询.大家都知道,像银行帐单流水一样,查几年的流水是常有的事. 支持的维度查询:帐期.欠费状态.日期范围.费用科目类型.房屋分类. ...
- composer 打印美化
{ "name": "brady_frmwork", "description":"php framwork", &qu ...
- 分布式机器学习:如何快速从Python栈过渡到Scala栈
首先介绍下我的情况和需求,如果你跟我类似,那么这篇文章将很有帮助: 我之前的技术栈主要是Java.Python,机器学习方面主要用到是pandas.numpy.sklearn.scipy.matplo ...
- Linux文件元数据和节点表结构
文件元数据 一块硬盘的分区可以认为有两部分组成,保存元数据的成为节点表,用来保存属性等. 元数据中有个小指针,指向数据存放的实际空间. 元数据(Metadata) 又称中介数据.中继数据,为描述数据的 ...
- Win10中装Win10---virtualbox虚拟机的安装及拓展
最近在准备一档专栏时,发现我电脑中已经把一些环境配置完了,卸掉重装又显得麻烦,于是我就求助于虚拟机,虚拟机确实是个很好的东西,不久前我的一个伙伴向我请教虚拟机怎么装,发现这玩意三言两语还很难说清,于是 ...
- 小白也能看懂的JVM内存区域
前言 最近在准备面试题刷到了JVM这块,作为一个小白,巩固知识点最好的方式就是亲手写出来并分享:相信我的理解,同样是小白的你,一定有很大的帮助.不信,请你往下看! JVM内存区域简介 如果有人问Jav ...