在.Net7源码中bool代码优化

起因

  • Streamline bool.TryParse/Format (#64782)
  • Fix bool.TryParse/Format on big-endian systems (#65078)

在.Net 6中TryParse

public static bool TryParse(ReadOnlySpan value, out bool result)
{
if (IsTrueStringIgnoreCase(value)) //关注IsTrueStringIgnoreCase
{
result = true;
return true;
}
if (IsFalseStringIgnoreCase(value)) //关注和IsFalseStringIgnoreCase
{
result = false;
return true;
}
value = TrimWhiteSpaceAndNull(value);
if (IsTrueStringIgnoreCase(value))
{
result = true;
return true;
}
if (IsFalseStringIgnoreCase(value))
{
result = false;
return true;
}
result = false;
return false;
}

在TryParse中,调用IsTrueStringIgnoreCase和IsFalseStringIgnoreCase这两个函数这时候是易读易懂.

专注于为中小企业提供网站建设、做网站服务,电脑端+手机端+微信端的三站合一,更高效的管理,为中小企业宜君免费做网站提供优质的服务。我们立足成都,凝聚了一批互联网行业人才,有力地推动了上千余家企业的稳健成长,帮助中小企业通过网站建设实现规模扩充和转变。

在.Net 7中TryParse(优化)

//只保留IsTrueStringIgnoreCase和IsFalseStringIgnoreCase
internal static bool IsTrueStringIgnoreCase(ReadOnlySpan value)
{
// "true" as a ulong, each char |'d with 0x0020 for case-insensitivity
// 先判断cpu支持大小端模式, 采用无符号long类型存储4个字符的ASCII码值 小端:: 65→e 75→u 72→r 74→t
// 将value转为byte数组,读取为ulong类型,然后或运算, 0x20为十六进制 是十进制32 或运算:: A | 32 = a 这样就不用区分大小写
// 0x0020002000200020为4个0x20,因为值一样,不区分大小端
ulong true_val = BitConverter.IsLittleEndian ? 0x65007500720074ul : 0x74007200750065ul;
return value.Length == 4 &&
(MemoryMarshal.Read(MemoryMarshal.AsBytes(value)) | 0x0020002000200020) == true_val;
}

internal static bool IsFalseStringIgnoreCase(ReadOnlySpan value)
{
// "fals" as a ulong, each char |'d with 0x0020 for case-insensitivity
// ulong类型只能存4个字符,所以存储 "fals"这4个字符 73→s 6c→l 61→a 66→f
// 最后1个字符进行与0x20进行或运算,得到小写字符和'e'进行判断
ulong fals_val = BitConverter.IsLittleEndian ? 0x73006C00610066ul : 0x660061006C0073ul;
return value.Length == 5 &&
(((MemoryMarshal.Read(MemoryMarshal.AsBytes(value)) | 0x0020002000200020) == fals_val) &
((value[4] | 0x20) == 'e'));
}

在.Net 6中TryFormat

public bool TryFormat(Span destination, out int charsWritten)
{
if (m_value) //为真
{
if ((uint)destination.Length > 3u)
{
//进行4次赋值操作
destination[0] = 'T';
destination[1] = 'r';
destination[2] = 'u';
destination[3] = 'e';
charsWritten = 4;
return true;
}
}
else if ((uint)destination.Length > 4u) //不为真
{
//进行5次赋值操作
destination[0] = 'F';
destination[1] = 'a';
destination[2] = 'l';
destination[3] = 's';
destination[4] = 'e';
charsWritten = 5;
return true;
}
charsWritten = 0;
return false;
}

在.Net 7中TryFormat(优化)

public bool TryFormat(Span destination, out int charsWritten)
{
if (m_value)
{
if ((uint)destination.Length > 3) // uint cast, per https://github.com/dotnet/runtime/issues/10596
{
//先判断cpu支持大小端模式, 采用无符号long类型存储4个字符的ASCII码值 小端:: 65→e 75→u 72→r 74→t
//将Span转为byte数组,将true_val写入,减少赋值的次数,与.Net 6中4次赋值操作,这里只有1次
ulong true_val = BitConverter.IsLittleEndian ? 0x65007500720054ul : 0x54007200750065ul; // "True"
MemoryMarshal.Write(MemoryMarshal.AsBytes(destination), ref true_val);
charsWritten = 4;
return true;
}
}
else
{
if ((uint)destination.Length > 4)
{
//不为真时,进行2次赋值操作 第1次 ulong 只能存4个字符, 第2次通过下标赋值为'e'
ulong fals_val = BitConverter.IsLittleEndian ? 0x73006C00610046ul : 0x460061006C0073ul; // "Fals"
MemoryMarshal.Write(MemoryMarshal.AsBytes(destination), ref fals_val);
destination[4] = 'e';
charsWritten = 5;
return true;
}
}

charsWritten = 0;
return false;
}

在.Net 7中对bool的改进,就是减少赋值操作,将4个字符转为ulong,实现了一次将4个字符赋值.还有通过位或操作巧妙的实现将大写字母进行转换.这种实现不是第一次看到,曾在wrk(压力工具,使用c语言编写)看到:

#define LOWER(c)     (unsigned char)(c | 0x20)

当前标题:在.Net7源码中bool代码优化
文章路径:http://www.shufengxianlan.com/qtweb/news29/54579.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联