当前位置: 首页 > 科技观察

.Net7源码中的bool代码优化

时间:2023-03-12 03:04:51 科技观察

原因代码总是从简单到复杂,从易读到晦涩,有的是业务逻辑复杂化,有的是为了性能优化,导致代码不是那么好读易懂。这里主要是看最近的.Netbool类型源码Change.Streamlinebool.TryParse/Format(#64782)Fixbool.TryParse/Formatonbig-endiansystems(#65078)in.Net6TryParsepublicstaticboolTryParse(ReadOnlySpanvalue,outboolresult){if(IsTrueStringIgnoreCase(value))//按照IsTrueStringIgnoreCase{result=true;返回真;}if(IsFalseStringIgnoreCase(value))//焦点和IsFalseStringIgnoreCase{result=false;返回真;}值=TrimWhiteSpaceAndNull(值);if(IsTrueString(Ignorevalue)){结果=true;返回真;}如果(IsFalseStringIgnoreCase(value)){结果=false;返回真;}结果=假;returnfalse;}在TryParse中,此时调用IsTrueStringIgnoreCase和IsFalseStringIgnoreCase这两个函数,很容易阅读和理解。In.Net7TryParse(optimized)//只保留IsTrueStringIgnoreCase和IsFalseStringIgnoreCaseinternalstaticboolIsTrueStringIgnoreCase(ReadOnlySpanvalue){//"true"为ulong,每个char|'dwith0x0020不区分大小写//首先确定cpu支持bigandsmallendian模式,使用unsignedlongtypetostore4字符littleendian的ASCII码值:65→e75→u72→r74→t//将value转为字节数组,读为ulong类型,然后OR运算,0x20是十六进制是十进制32或操作::A|32=a这样就不需要区分大小写//0x0020002000200020是40x20,因为值是一样的,不区分大小写ulongtrue_val=BitConverter.IsLittleEndian?0x65007500720074ul:0x74007200750065ul;returnvalue.Length(==MemoryMarshal.Read(MemoryMarshal.AsBytes(value))|0x0020002000200020)==true_val;}internalstaticboolIsFalseStringIgnoreCase(ReadOnlySpanvalue){//“fals”作为一个ulong,eachchar|'dwith0x0020forcase-insensitive//ulong类型只能存储4个字符,所以存储4个字符"fals"73→s6c→l61→a66→f//最后一个字符与0x20获取小写字符和'e'被判断ulongfals_val=BitConverter.IsLittleEndian?0x73006C00610066ul:0x660061006C0073ul;返回值.Length==5&&(((MemoryMarshal.Read(MemoryMarshal.AsBytes(value))|0x0020002000200020)==fals_val)&((value[4]|0x20)=='e'));}In.Net6TryFormatpublicboolTryFormat(Spandestination,outintcharsWritten){if(m_value)//True{if((uint)destination.Length>3u){//进行4次赋值操作destination[0]='T';目的地[1]='r';目的地[2]='你';目的地[3]='e';charsWritten=4;返回真;}}elseif((uint)destination.Length>4u)//nottrue{//执行了5次赋值操作destination[0]='F';目的地[1]='a';目的地[2]='l';目的地[3]='s';目的地[4]='e';charsWritten=5;返回真;}charsWritten=0;returnfalse;}in.Net7TryFormat(optimized)publicboolTryFormat(Spandestination,outintcharsWritten){if(m_value){if((uint)destination.Length>3)//uintcast,perhttps://img.ydisp.cn/news/20220902/sip3tu0afct{//首先确定cpu支持大小端模式,使用unsignedlong类型存储4个字符的ASCII码值littleendian::65→e75→u72→r74→t//将Span转换为byte数组,将true_val写入其中,减少赋值次数。与.Net6中的4个赋值操作相比,只有一个ulongtrue_val=BitConverter。是LittleEndian吗?0x65007500720054ul:0x54007200750065ul;//“真”MemoryMarshal.Write(MemoryMarshal.AsBytes(destination),reftrue_val);charsWritten=4;返回真;}}else{destination>4(uint)){//如果不为真,进行2次赋值操作。第一个ulong只能存4个字符,第二个通过下标赋值为'e'ulongfals_val=BitConverter.IsLittleEndian?0x73006C00610046ul:0x460061006C0073ul;//"错误"MemoryMarshal.Write(MemoryMarshal.AsBytes(目的地),reffals_val);目的地[4]='e';charsWritten=5;返回真;}}charsWritten=0;returnfalse;}在.Net7中对bool的改进是减少了赋值操作,将4个字符转为ulong,实现了一次对4个字符的赋值。还有一个巧妙的实现是通过bit-or操作来转换大写字母。这不是我第一次看到它,曾经在wrk(压力工具,用c语言编写)中看到过:#defineLOWER(c)(unsignedchar)(c|0x20)