根据 Performance Improvements in .NET Core 2.1 一文总结。比较的对象为 .Net Core 2.0。
EqualityComparer<T>.Default.Equals 能被 intrinsic 识别,devirtualize 并 inline,带来 ~2.5x 的性能提升。Dictionary<Tkey,TValue> 的 ContainsValue 也提升了 ~2.25x;上面基本上给所有的集合类搜索都带来了可观的提升。EqualityComparer<T>.Default.Equals,而不是先将 EqualityComparer<T>.Default 放到一个变量,然后用那个变量的 Equal 方法,这种微优化由于 JIT 识别不出来,无法生成高效的代码从而变成了负优化。((IAnimal)thing).MakeSound() 这样通过接口来调用 struct 方法的代码(其中 thing 为 struct),避免装箱和接口方法调用,直接调用成员方法,并且尽可能 inline。~10x 的性能提升,并且不会 allocated。// 在 .net core 2.1 后不会 box
[Benchmark]
public void BoxingAllocations() => BoxingAllocations(default(Dog));
private void BoxingAllocations<T>(T thing)
{
if (thing is IAnimal)
((IAnimal)thing).MakeSound();
}
private struct Dog : IAnimal
{
public void Bark() { }
void IAnimal.MakeSound() => Bark();
}
private interface IAnimal
{
void MakeSound();
}
CancellationTokenSource. CancellationToken 的关注重点从 scalability 更改为 throughput 和 allocation,实现了 ~1.7x 的性能提升和 0 分配。ValueTask 的话不会在堆上分配。即使不是使用 ValueTask,对于已经完成的任务,框架在很多情况下会使用已经缓存的同一个 Task<int/bool/etc..> 来避免分配。class 变成了 struct,并使用 in 传参。)Span<T>.SequenceEqual 来向量化 String.Equal,性能提升 ~1.6x。String.IndexOf 和 String.LastIndexOf, ~2.7x。String.IndexOfAny ~2.5x。String.ToLower 和 ToUpper(包括 ToLower/UpperInvariant)在需要转换时 ~3x;在不需要转换(即字符已经符合目标)时 ~2x,而且不再有 allocated。String.Split,视字符串的长度或使用栈上分配或使用 ArrayPool<int>.Shared 来消除原先用来记录字符串分段的 Int32[] 分配。再辅以 span 的优势来改善常见情形的 throughput,性能提升 ~1.5x,分配只为原来的 1/4。String.Concat(IEnumerable<char>) ~1.5x,分配为原来的 1/9。string.Format 性能 ~1.3x,分配为 2/3。StringBuilder.Append 性能 ~2x,分配为 0。Int32.ToString() ~2x;int.Parse ~1.3x。Int32, UInt32, Int64, UInt64, Single, Double 的 ToString() 也一样改进。尤其在 unix 有将近 10 倍的提升。BigInteger.ToString ~12x!并且 allocated 只为原先的 1/17。DateTime 和 DateTimeOffset 的 R 和 O 的 ToString,分别提升 ~4x 和 ~2.6x。Convert.FromBase64String ~1.5x;Convert.FromBase64CharArray ~1.6x。Dns.GetHostAddressAsync 在 windows 上变成了真·异步操作。IPAddress.HostToNetworkOrder/NetworkToHostOrder ~8x。Uri 的分配降低到原来的一半,初始化 ~1.5x。Socket 收发 ~2x。SslStream 中的分配,修正它在 unix 中的瓶颈。HttpClient 现在使用完全 C# 编写的 SocketsHttpHandler,一个用 Socket SslStream 和 NetworkStream 做服务端,用 HttpClient 做客户端通过 https 访问的示例,获得了 12.7 倍的性能飙升!同时分配也大大减少,也没了 Gen1 对象。Directory.EnumerateFiles ~3x,allocated 1/2。System.Security.Cryptography.Rfc2898DeriveBytes.GetBytes 由于 Span 的使用完全消除了计算过程中的分配。总的分配:1120120 B -> 176 B,性能有所提高。Guid.NewGuid() 在 unix 上有 4 倍的提升。Regex.Compiled 回来了而且生效,Match 性能提高约一倍。