.NET8极致性能优化CHRL
前言
.NET8在.NET7的基础上进行了进一步的优化,比如CHRL(全称:CORINFO_HELP_RNGCHKFAIL)优化技术,CORINFO_HELP_RNGCHKFAIL是边界检查,在.NET7里面它已经进行了部分优化,但是.NET8里面它继续优化,类似人工智能,.NET8能意识到某些性能问题,从而进行优化。本篇来看下
原文地址:.NET8极致性能优化CHRL
概述
JIT会对数组,字符串的范围边界进行检查。比如数组的索引是否在数组长度范围内,不能超过。所以JIT就会产生边界检查的步骤。
public class Tests { private byte[] _array = new byte[8]; private int _index = 4; public void Get() => Get(_array, _index); [MethodImpl(MethodImplOptions.NoInlining)] private static byte Get(byte[] array, int index) => array[index]; }
Get函数.NET7的ASM如下:
; Tests.Get(Byte[], Int32) sub rsp,28 cmp edx,[rcx+8] jae short M01_L00 mov eax,edx movzx eax,byte ptr [rcx+rax+10] add rsp,28 ret M01_L00: call CORINFO_HELP_RNGCHKFAIL int 3
cmp指令把数组的MT(方法表)偏移8位置的数组长度与当前的数组索引对比,两者如果索引大于(后者)或等于(jae)数组长度(前者)的时候。就会跳转到CORINFO_HELP_RNGCHKFAIL进行边界检查,可能会引发超出引范围的异常IndexOutOfRangeException。但是实际上这段这段代码的访问只需要两个mov,一个是数组的索引,一个是(MT(方法表)+0x10+索引)取其值返回即可。所以这个地方有清晰可见的优化的地方。
.NET8学习了一些范围边界的智能化优化,也就说,有的地方不需要边界检查,从而把边界检查优化掉,用以提高代码的性能。下面例子:
private readonly int[] _array = new int[7]; public int GetBucket() => GetBucket(_array, 42); private static int GetBucket(int[] buckets, int hashcode) => buckets[(uint)hashcode % buckets.Length];
.NET7它的ASM如下:
; Tests.GetBucket() sub rsp,28 mov rcx,[rcx+8] mov eax,2A mov edx,[rcx+8] mov r8d,edx xor edx,edx idiv r8 cmp rdx,r8 jae short M00_L00 mov eax,[rcx+rdx*4+10] add rsp,28 ret M00_L00: call CORINFO_HELP_RNGCHKFAIL int 3
它依然进行了边界检查,然.NET8的JIT能自动识别到(uint)hashcode%buckets.Length这个索引不可能超过数组的长度也就是buckets.Length。所以.NET8可以省略掉边界检查,如下.NET8 ASM
; Tests.GetBucket() mov rcx,[rcx+8] mov eax,2A mov r8d,[rcx+8] xor edx,edx div r8 mov eax,[rcx+rdx*4+10] ret
再看下另外一个例子:
public class Tests { private readonly string _s = "\"Hello, World!\""; public bool IsQuoted() => IsQuoted(_s); private static bool IsQuoted(string s) => s.Length >= 2 && s[0] == '"' && s[^1] == '"'; }
IsQuoted检查字符串是否至少有两个字符,并且字符串开头和结尾均以引号结束,s[^1]表示s[s.Length - 1]也就是字符串的长度。.NET7 ASM如下:
; Tests.IsQuoted(System.String) sub rsp,28 mov eax,[rcx+8] cmp eax,2 jl short M01_L00 cmp word ptr [rcx+0C],22 jne short M01_L00 lea edx,[rax-1] cmp edx,eax jae short M01_L01 mov eax,edx cmp word ptr [rcx+rax*2+0C],22 sete al movzx eax,al add rsp,28 ret M01_L00: xor eax,eax add rsp,28 ret M01_L01: call CORINFO_HELP_RNGCHKFAIL int 3
注意看.NET7的骚操,它实际上进行了边界检查,但是只检查了一个,因为它只有一个jae指令跳转。这是为什么呢?JIT已经知道不需要对s[0]进行边界检查,因为s.Length >= 2已经检查过了,只要是小于2的索引(因为索引是无符号,没有负数)都不需要检查。但是依然对s[s.Length - 1]进行了边界检查,所以.NET7虽然也是骚操,但是它这个骚操不够彻底。
我们来看下彻底骚操的.NET8
; Tests.IsQuoted(System.String) mov eax,[rcx+8] cmp eax,2 jl short M01_L00 cmp word ptr [rcx+0C],22 jne short M01_L00 dec eax cmp word ptr [rcx+rax*2+0C],22 sete al movzx eax,al ret M01_L00: xor eax,eax ret
完全没有了边界检查,JIT不仅意识到s[0]是安全的,因为检查过了s.Length >= 2。因为检查过了s.Length >= 2,还意识到s.length> s.Length-1 >=1。所以不需要边界检查,全给它优化掉了。
可以看到.NET8的性能优化的极致有多厉害,它基本上榨干了JIT的引擎,让其进行最大智能化程度的优化。
点击下加入技术讨论群:
欢迎加入.NET技术交流群

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
有理有据:数据库选择集中式还是分布式
OLTP类型的业务系统采用集中式数据库还是分布式数据库是在做国产数据库改造中经常被问到的问题,无论是对技术架构发展演变,还是对现有业务长期发展提供必要的支撑,这个问题都具有讨论意义。在分布式大行其道的背景下,似乎任何架构都需要分布式赋能。现实真的是这样吗?下面将全面地进行分析与阐述。 作者:王辉 文章来源于微信公众号“基础技术研究” 一、使用现状分析 国产数据库厂商2022年就已经达到了200多家,传统集中式数据库以人大金仓、达梦为主,也有像polarDB这样的新兴数据库,分布式数据库有GaussDB、Kingwow、TDSQL、GoldenDB和OceanBase等,其实大部分这类的数据库都具备集中式和分布式两种部署模式,也就是你买分布式数据库的钱也可以用于集中式部署,可以满足你不同的业务需求。 这里有一点要注意,有的分布式数据库的厂商采用集中式部署,应用依然需要连接计算节点。通过计算节点(CN),去连接下面的数据节点,这可能是出于统一架构的考虑,也是出于计算节点在数据库发生主备切换时可以感知自动切换、对应用透明的考虑。但这样无意中增加了一层解析,会对性能产生一定的损耗。有的数据库厂...
- 下一篇
如何画出规范的 UML 用例图
如果你在做设计过程中有一些困惑,如:不会找用例、两个用例图分不清楚、不知道自己画的对不对。那么希望本文能帮助厘清上面几个问题,真正掌握用例图,在后面的设计中能运用的得心应手。 在做设计的时候你是否有以下困惑? 1.不会找用例:业务用例、系统用例又都是啥啊?我该如何把用例写对啊? 2.两个用例图分不清楚:业务用例图和系统用例图感觉好像啊,似乎没啥区别啊? 3.不知道自己画的对不对:照猫画虎画了个用例图,但是我也不知道画的对不对,万一评审的人也不会呢,就这样交差吧 如果你在做设计过程中有以上困惑,那么希望本文能帮助厘清上面几个问题,真正掌握用例图,在后面的设计中能运用的得心应手。 一、如何识别正确的用例 首先看用例的概念,百科上定义“用例是软件工程或系统工程中对系统如何反应外界请求的描述,是一种通过用户的使用场景来获取需求的技术”。什么意思呢,这里我引用《大象:Thinking in UML》里面的一段话来解释下这个定义 这个世界的功能性体现在,首先有某人的一个愿望,这个愿望驱使人去做事并获得一个确定的结果。如果没有愿望,功能性就无从谈起。一个系统就是由各种各样的愿望组成的,换句话说,各种...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- CentOS7,8上快速安装Gitea,搭建Git服务器
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- CentOS8编译安装MySQL8.0.19
- CentOS7,CentOS8安装Elasticsearch6.8.6