ASP.NET Core 6 的性能改进

点击上方蓝字
关注我们
(本文阅读所需15分钟)
受到由 Stephen Toub 发布的关于 .NET 性能的博客的启发 , 我们正在写一篇类似的文章来强调 ASP.NET Core 在 6.0 中所做的性能改进 。

  • .NET 性能 https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-6/
基准设置
我们整个过程中大部分的实例使用的是 BenchmarkDotNet 。 在 githup 上提供了repo 。 其中还包括本文中使用的大多数基准 。
本文中的大多数基准测试结果都是通过以下命令行生成的:
dotnetrun-cRelease-fnet48--runtimesnet48netcoreapp3.1net5.0net6.0 然后从列表中选择要运行的特定基准 。
这命令行给 BenchmarkDotNet 指令:
  • 在发布配置中构建所有内容
  • 针对 .NET Framework 4.8 外围区域构建它
  • 在 .NET Framework 4.8、.NET Core 3.1、.NET 5 和 .NET 6 上运行每个基准测试
  • 对于某些基准测试 , 它们仅在 .NET 6 上运行(例如 , 如果比较同一版本上的编码的两种方式): dotnet run -c Release -f net6.0 --runtimes net6.0
对于其他人 , 只运行了版本的一个子集 , 例如
dotnet run -c Release -f net5.0 --runtimes net5.0 net6.0
我将包括用于运行每个基准测试的命令
本文中的大多数结果都是在 Windows 上运行上述基准测试生成的 , 主要是为了将. NET Framework 4.8包含在结果集中 。 但是 , 除非另有说明 , 一般来说 , 所有这些基准测试在 Linux 或 macOS 上运行时都显示出相当显著的改进 。 只需确保您已经安装了想要测量的每个运行时 。 这些基准测试使用的是 .NET 6 RC1 的构建 , 以及最新发布的 .NET 5 和.NET Core 3.1下载 。
span< T >
自从在.NET 2.1中增加了Span<T>,之后的每一个版本我们都转换了更多的代码以在内部和作为公共API的一部分使用Span来提高性能 。 这次发布也不例外 。
PR dotnet/aspnetcore#28855 在添加两个 PathString 实例时删除了来自 string.SubString 的 PathString 中的临时字符串分配 , 而是使用 Span<char> 作为临时字符串 。 在下面的基准测试中 , 我们使用一个短字符串和一个长字符串来显示避免使用临时字符串的性能差异 。
dotnet run -c Release -f net48 --runtimes net48 net5 .0net6 .0--filter *PathStringBenchmark*privatePathString _first = newPathString( "/first/"); privatePathString _second = newPathString( "/second/"); privatePathString _long = newPathString( "/longerpathstringtoshowsubstring/");
[ Benchmark] publicPathString AddShortString( ) {return_first.Add(_second); }
[ Benchmark] publicPathString AddLongString( ) {return_first.Add(_long); }
ASP.NET Core 6 的性能改进
文章图片

dotnet/aspnetcore#34001 引入了一个新的基于 Span 的 API , 用于枚举查询字符串 , 在没有编码字符的常见情况下 , 该查询字符串是分配空闲的 , 当查询字符串包含编码字符时 , 分配更低 。
dotnet run -c Release -f net6.0 --runtimes net6.0 --filter *QueryEnumerableBenchmark*
#if NET6_0_OR_GREATERpublic enum QueryEnum{Simple = 1,Encoded,}[ParamsAllValues]public QueryEnum QueryParam { get; set; }private string SimpleQueryString = "?key1=value1&key2=value2";private string QueryStringWithEncoding = "?key1=valu%20&key2=value%20";[Benchmark(Baseline = true)]public void QueryHelper{var queryString = QueryParam == QueryEnum.Simple ? SimpleQueryString : QueryStringWithEncoding;foreach (var queryParam in QueryHelpers.ParseQuery(queryString)){_ = queryParam.Key;_ = queryParam.Value;}}[Benchmark]public void QueryEnumerable{var queryString = QueryParam == QueryEnum.Simple ? SimpleQueryString : QueryStringWithEncoding;foreach (var queryParam in new QueryStringEnumerable(queryString)){_ = queryParam.DecodeName;_ = queryParam.DecodeValue;}}#endif

特别声明:本站内容均来自网友提供或互联网,仅供参考,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。