using System; using System.Diagnostics; public class Test { a = 99, b = 10, div, rem; Main() { var sw = Stopwatch.StartNew(); for (int i = 0; i < 100_000_000; i++) { div = Math.DivRem(a, b, out rem); } Console.WriteLine(sw.Elapsed); } }
00:00:01.4143100
并在.NET Core 2.0上得到如下结果:
00:00:00.7469733
吞吐量提高约2倍。
序列化
二进制序列化是.NET的另一个领域。BinaryFormatter最初并不是.NET Core中的一个组件,但是它包含在.NET Core 2.0中。该组件在性能方面有比较巧妙的修复。例如,PR dotnet / corefx#17949是一种单行修复,可以增加允许增长的最大大小的特定数组,但是这一变化可能对吞吐量产生重大影响,通过O(N)算法比以前的O(N ^ 2)算法要话费更长的操作时间。以下代码示例,明显的展示了这一点:
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Runtime.Serialization.Formatters.Binary; class Test { static void Main() { var books = new List<Book>(); for (int i = 0; i < 1_000_000; i++) { string id = i.ToString(); books.Add(new Book { Name = id, Id = id }); } var formatter = new BinaryFormatter(); var mem = new MemoryStream(); formatter.Serialize(mem, books); mem.Position = 0; var sw = Stopwatch.StartNew(); formatter.Deserialize(mem); sw.Stop(); Console.WriteLine(sw.Elapsed.TotalSeconds); } [Serializable] private class Book { public string Name; public string Id; } }
在.NET 4.7中,代码输出如下结果:
76.677144
而在.NET Core 2.0中,会输出如下结果:
6.4044694
在这种情况下显示出了12倍的吞吐量提高。换句话说,它能够更有效地处理巨大的序列化输入。
文字处理
.NET应用程序中另一种很常见的计算形式就是处理文本,文字处理在堆栈的各个层次上都有大量的改进。
对于正则表达式,通常用于验证和解析输入文本中的数据。以下是使用Regex.IsMatch重复匹配电话号码的示例:
using System; using System.Diagnostics; using System.Text.RegularExpressions; public class Test { Main() { var sw = new Stopwatch(); int gen0 = GC.CollectionCount(0); sw.Start(); for (int i = 0; i < 10_000_000; i++) { Regex.IsMatch(, ); } Console.WriteLine($); } }
在个人计算机上,.NET 4.7会得到的如下结果:
Elapsed=00:00:05.4367262 Gen0=820 Gen1=0 Gen2=0
而使用.NET Core 2.0会得到如下结果:
Elapsed=00:00:04.0231373 Gen0=248
由于PR dotnet / corefx#231的变化很小,这些修改有助于缓存一部分数据,因此吞吐量提高了25%,分配/垃圾收集减少了70%。
文本处理的另一个例子是各种形式的编码和解码,例如通过WebUtility.UrlDecode进行URL解码。在这种解码方法中,通常情况下输入不需要任何解码,但是如果输入经过了解码器,则输入仍然可以通过。感谢来自hughbe的 PR dotnet / corefx#7671,这种情况已经被优化了。例如下面这段程序:
using System; using System.Diagnostics; using System.Net; public class Test { Main() { var sw = new Stopwatch(); int gen0 = GC.CollectionCount(0); sw.Start(); for (int i = 0; i < 10_000_000; i++) { WebUtility.UrlDecode(); } Console.WriteLine($); } }
在.NET 4.7中,会得到以下输出:
Elapsed=00:00:01.6742583 Gen0=648
而在.NET Core 2.0中,输出如下:
Elapsed=00:00:01.2255288 Gen0=133
其他形式的编码和解码也得到了改进。例如,dotnet / coreclr#10124优化了使用一些内置Encoding -derived类型的循环。例如下面的示例: