.NET 7的性能改进有哪些具体细节?
摘要:原文 | Stephen Toub 翻译 | 郑子铭 最后一个有趣的与IndexOf有关的优化。字符串早就有了IndexOfIndexOfAnyLastIndexOfLastIndexOfAny,显然对于字符串来说,这都是关于处理字符
原文 | Stephen Toub
翻译 | 郑子铭
最后一个有趣的与IndexOf有关的优化。字符串早就有了IndexOf/IndexOfAny/LastIndexOf/LastIndexOfAny,显然对于字符串来说,这都是关于处理字符。当ReadOnlySpan和Span出现时,MemoryExtensions被添加进来,为spans和朋友提供扩展方法,包括这样的IndexOf/IndexOfAny/LastIndexOf/LastIndexOfAny方法。但是对于spans来说,这不仅仅是char,所以MemoryExtensions增长了它自己的一套实现,基本上与string的实现分开。多年来,MemoryExtensions的实现已经专门化了越来越多的类型,但特别是字节和char,这样一来,随着时间的推移,string的实现大多被委托到与MemoryExtensions使用的相同的实现中而取代。然而,IndexOfAny和LastIndexOfAny一直是统一的保留者,它们各有自己的方向。string.IndexOfAny对于被搜索的1-5个值确实委托给与MemoryExtensions.IndexOfAny相同的实现,但是对于超过5个值,string.IndexOfAny使用一个 "概率图",基本上是一个布鲁姆过滤器。它创建了一个256位的表,并根据被搜索的值快速设置该表中的位(本质上是散列,但用一个微不足道的散列函数)。然后,它对输入进行迭代,而不是将每个输入字符与每个目标值进行对照,而是首先在表中查找输入字符。如果相应的位没有被设置,它就知道输入的字符与任何目标值都不匹配。如果相应的位被设置,那么它就会继续将输入的字符与每个目标值进行比较,它很有可能是其中之一。MemoryExtensions.IndexOfAny对5个以上的值缺乏这样的过滤器。相反,string.LastIndexOfAny没有为多个目标值提供任何矢量,而MemoryExtensions.LastIndexOfAny则为两个和三个目标值提供矢量。从dotnet/runtime#63817开始,所有这些现在都是统一的,这样字符串和MemoryExtensions都得到了对方的优点。
