using System; using System.Diagnostics; using System.Linq; using System.Text; public class Test { Main() { + i)).ToArray()); while (true) { var sw = Stopwatch.StartNew(); for (int i = 0; i < 1_000_000; i++) { byte[] data = Encoding.UTF8.GetBytes(s); } Console.WriteLine(sw.Elapsed); } } }
在.NET 4.7中得到以下输出,如:
::00:02.3550876
而.NET Core 2.0等到如下输出:
::00:01.6070767
这些改进也适用于字符串和其它类型之间转换,例如.NET中生成Parse和ToString方法。使用枚举来表示各种状态是相当普遍的,例如使用Enum.Parse将字符串解析为相应的枚举。PR dotnet / coreclr#2933改善了这一点。请查看以下的代码:
using System; using System.Diagnostics; public class Test { Main() { while (true) { var sw = new Stopwatch(); int gen0 = GC.CollectionCount(0); sw.Start(); for (int i = 0; i < 2_000_000; i++) { Enum.Parse(); } Console.WriteLine($); } } [Flags] private enum Colors { Red = 0x1, Orange = 0x2, Yellow = 0x4, Green = 0x8, Blue = 0x10 } }
在.NET 4.7中,会得到的以下结果:
Elapsed=00:00:00.9529354 Gen0=293 Elapsed=00:00:00.9422960 Gen0=294 Elapsed=00:00:00.9419024 Gen0=294 Elapsed=00:00:00.9417014 Gen0=294 Elapsed=00:00:00.9514724 Gen0=293
在.NET Core 2.0上,会得到以下结果:
Elapsed=00:00:00.6448327 Gen0=11 Elapsed=00:00:00.6438907 Gen0=11 Elapsed=00:00:00.6285656 Gen0=12 Elapsed=00:00:00.6286561 Gen0=11 Elapsed=00:00:00.6294286 Gen0=12
不但吞吐量提高了约33%,而且分配和相关垃圾收集也减少了约25倍。
当然,在.NET应用程序中需要进行大量的自定义文本处理,除了使用像Regex / Encoding这样的内置类型和Parse和ToString这样的内置操作之外,文本操作通常都是直接构建在字符串之上,并且大量的改进已经引入到了操作on String之上。
例如,String.IndexOf很擅长于查找字符串中的字符。IndexOf在bnetyersmyth的dotnet / coreclr#5327中得到改进,他们为String实现了一系列的性能改进。正如下面的例子:
using System; using System.Diagnostics; public class Test { Main() { var dt = DateTime.Now; while (true) { var sw = new Stopwatch(); int gen0 = GC.CollectionCount(0); sw.Start(); for (int i = 0; i < 2_000_000; i++) { dt.ToString(); dt.ToString(); } Console.WriteLine($); } } }
在.NET 4.7上,会得到如下结果:
::00:05.9622262
而在.NET Core 2.0中,会得到如下结果:
:00:02.9778923 00:00:03.0782851
吞吐量提高约2倍。
下面是比较字符串部分。这是一个使用String.StartsWith和序数比较的例子: