.NET 7的性能改进有哪些具体细节?
摘要:原文 | Stephen Toub 翻译 | 郑子铭 原始类型和数值 (Primitive Types and Numerics) 我们已经看过了代码生成和GC,线程和矢量化,互操作......让我们把注意力转向系统中的一些基本类型。像in
原文 | Stephen Toub
翻译 | 郑子铭
原始类型和数值 (Primitive Types and Numerics)
我们已经看过了代码生成和GC,线程和矢量化,互操作......让我们把注意力转向系统中的一些基本类型。像int、bool和double这样的基本类型,像Guid和DateTime这样的核心类型,它们构成了构建一切的支柱,每一个版本都能看到这些类型的改进,这让人兴奋。
来自@CarlVerret的dotnet/runtime#62301极大地提高了double.Parse和float.Parse将UTF16文本解析为浮点值的能力。这一点特别好,因为它是基于@lemire和@CarlVerret最近的一些研究,他们用C#和.NET 5实现了一个非常快速的浮点数解析实现,而这个实现现在已经进入了.NET 7!
private string[] _valuesToParse;
[GlobalSetup]
public void Setup()
{
using HttpClient hc = new HttpClient();
string text = hc.GetStringAsync("https://raw.githubusercontent.com/CarlVerret/csFastFloat/1d800237275f759b743b86fcce6680d072c1e834/Benchmark/data/canada.txt").Result;
var lines = new List<string>();
foreach (ReadOnlySpan<char> line in text.AsSpan().EnumerateLines())
{
ReadOnlySpan<char> trimmed = line.Trim();
if (!trimmed.IsEmpty)
{
lines.Add(trimmed.ToString());
}
}
_valuesToParse = lines.ToArray();
}
[Benchmark]
public double ParseAll()
{
double total = 0;
foreach (string s in _valuesToParse)
{
total += double.Parse(s);
}
return total;
}
方法
运行时
平均值
比率
ParseAll
.NET 6.0
26.84 ms
1.00
ParseAll
.NET 7.0
12.63 ms
0.47
bool.TryParse和bool.TryFormat也得到了改进。dotnet/runtime#64782通过使用BinaryPrimitives执行更少的写和读,简化了这些实现。例如,TryFormat通过执行以下操作而不是写出 "True"。
destination[0] = 'T';
destination[1] = 'r';
destination[2] = 'u';
destination[3] = 'e';
这需要四次写操作,相反,它可以通过一次写来实现相同的操作。
BinaryPrimitives.WriteUInt64LittleEndian(MemoryMarshal.AsBytes(destination), 0x65007500720054); // "True"
那0x65007500720054是内存中四个字符的数值,是一个单一的ulong。你可以通过一个微观的基准测试看到这些变化的影响。
