除了单个字符之外,实际上在.NET Core的每个版本中,我们都在努力提高现有格式化api的速度。这次发布也没有什么不同。尽管之前的版本取得了巨大的成功,但这一版本将门槛进一步提高。
Int32.ToString() 是一个非常常见的操作,重要的是它要快。来自@ts2do的dotnet/runtime#32528 通过为该方法使用的关键格式化例程添加不可链接的快速路径,并通过简化各种公共api到达这些例程的路径,使其更快。其他原始ToString操作也得到了改进。例如,dotnet/runtime#27056简化了一些代码路径,以减少从公共API到实际将位写入内存的位置的冗余。
Method Runtime Mean Ratio Allocated
ToString12345 .NET FW 4.8 45.737 ns 1.00 40 B
ToString12345 .NET Core 3.1 20.006 ns 0.44 32 B
ToString12345 .NET 5.0 10.742 ns 0.23 32 B
ToString123 .NET FW 4.8 42.791 ns 1.00 32 B
ToString123 .NET Core 3.1 18.014 ns 0.42 32 B
ToString123 .NET 5.0 7.801 ns 0.18 32 B
类似的,在之前的版本中,我们对DateTime和DateTimeOffset做了大量的优化,但这些改进主要集中在日/月/年/等等的转换速度上。将数据转换为正确的字符或字节,并将其写入目的地。在dotnet/runtime#1944中,@ts2do专注于之前的步骤,优化提取日/月/年/等等。DateTime{Offset}从原始滴答计数中存储。最终非常富有成果,导致能够输出格式如“o”(“往返日期/时间模式”)比以前快了30%(变化也应用同样的分解优化在其他地方在这些组件的代码库需要从一个DateTime,但改进是最容易显示在一个标准格式):
FormatChars .NET Core 3.1 242.4 ns 1.00
FormatChars .NET 5.0 176.4 ns 0.73
FormatBytes .NET Core 3.1 235.6 ns 1.00
FormatBytes .NET 5.0 176.1 ns 0.75
对字符串的操作也有很多改进,比如dotnet/coreclr#26621和dotnet/coreclr#26962,在某些情况下显著提高了区域性感知的Linux上的起始和结束操作的性能。
当然,低级处理是很好的,但是现在的应用程序花费了大量的时间来执行高级操作,比如以特定格式编码数据,比如之前的.NET Core版本是对Encoding.UTF8进行了优化,但在.NET 5中仍有进一步的改进。dotnet/runtime#27268优化它,特别是对于较小的投入,以更好地利用堆栈分配和改进了JIT devirtualization (JIT是能够避免虚拟调度由于能够发现实际的具体类型实例的处理)。
Roundtrip .NET FW 4.8 113.69 ns 1.00 96 B
Roundtrip .NET Core 3.1 49.76 ns 0.44 96 B
Roundtrip .NET 5.0 36.70 ns 0.32 96 B