【翻译】.NET 5中的性能改进 (18)


在.NET Core之前的版本中,系统出现了大量的变动。Linq代码基,特别是提高性能。这个流程已经放缓了,但是.NET 5仍然可以看到LINQ的性能改进。
OrderBy有一个值得注意的改进。正如前面所讨论的,将coreclr的本地排序实现转换为托管代码有多种动机,其中一个就是能够轻松地将其作为基于spanc的排序方法的一部分进行重用。这样的api是公开的,并且通过,我们能够在System.Linq中利用基于spane的排序。这特别有好处,因为它支持利用基于Comparison的排序例程,这反过来又支持避免在每个比较操作上的多层间接。

[GlobalSetup] public void Setup() { var r = new Random(42); _array = Enumerable.Range(0, 1_000).Select(_ => r.Next()).ToArray(); } private int[] _array; [Benchmark] public void Sort() { foreach (int i in _array.OrderBy(i => i)) { } } Method Runtime Mean Ratio
Sort   .NET FW 4.8   100.78 us   1.00  
Sort   .NET Core 3.1   101.03 us   1.00  
Sort   .NET 5.0   85.46 us   0.85  


对于一行更改来说,这还不错。
另一个改进是来自@timandy的dotnet/corefx#41342。PR可扩充的枚举。SkipLast到特殊情况IList以及内部IPartition接口(这是各种操作符相互之间进行优化的方式),以便在可以廉价确定源长度时将SkipLast重新表示为Take操作。

private IEnumerable<int> data = Enumerable.Range(0, 100).ToList(); [Benchmark] public int SkipLast() => data.SkipLast(5).Sum(); Method Runtime Mean Ratio Allocated
SkipLast   .NET Core 3.1   1,641.0 ns   1.00   248 B  
SkipLast   .NET 5.0   684.8 ns   0.42   48 B  


最后一个例子,dotnet/corefx#40377是一个漫长的过程。这是一个有趣的例子。一段时间以来,我看到开发人员认为Enumerable.Any()比Enumerable.Count() != 0更有效;毕竟,Any()只需要确定源中是否有东西,而Count()需要确定源中有多少东西。因此,对于任何合理的集合,any()在最坏情况下应该是O(1),而Count()在最坏情况下可能是O(N),那么any()不是总是更好的吗?甚至有Roslyn分析程序推荐这种转换。不幸的是,情况并不总是这样。在。net 5之前,Any()的实现基本如下:

using (IEnumerator<T> e = source.GetEnumerator) return e.MoveNext();


这意味着在通常情况下,即使可能是O(1)操作,也会导致分配一个枚举器对象以及两个接口分派。相比之下,自从. net Framework 3.0中LINQ的初始版本发布以来,Count()已经优化了特殊情况下ICollection使用它的Count属性的代码路径,在这种情况下,它通常是O(1)和分配自由,只有一个接口分派。因此,对于非常常见的情况(比如源是List),使用Count() != 0实际上比使用Any()更有效。虽然添加接口检查会带来一些开销,但值得添加它以使Any()实现具有可预测性并与Count()保持一致,这样就可以更容易地对其进行推理,并使有关其成本的主流观点变得正确。

Networking


如今,网络是几乎所有应用程序的关键组件,而良好的网络性能至关重要。因此,.NET的每一个版本都在提高网络性能上投入了大量的精力.NET 5也不例外。
让我们先看看一些原语,然后继续往下看。系统。大多数应用程序都使用Uri来表示url,它的速度要快,这一点很重要。许多PRs已经开始在。.NET 5中使Uri更快。可以说,Uri最重要的操作是构造一个Uri,而dotnet/runtime#36915使所有Uri的构造速度更快,主要是通过关注开销和避免不必要的开销:

[Benchmark] public Uri Ctor() => new Uri("http://github.com/dotnet/runtime/pull/36915"); Method Runtime Mean Ratio Allocated
Ctor   .NET FW 4.8   443.2 ns   1.00   225 B  
Ctor   .NET Core 3.1   192.3 ns   0.43   72 B  
Ctor   .NET 5.0   129.9 ns   0.29   56 B  

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsssyf.html