.Net 7性能改进-前言

前言

这是一篇 Performance Improvements in .NET 7 的翻译,原文比较长,PDF文件有232页,所以进行了拆分,每天翻译一部分.下面便开始正文:

一年前,我(Stephen Toub)写了 .Net 6性能改进 这篇文章,类似的还有 .NET Core 2.0 和 .NET Core 2.1 及 .NET Core 3.0 /.NET 5 ,我喜欢写这些文章,喜欢阅读开发人员对它们的回应.特别是去年的一条评论引起了我的共鸣.该评论引用了《 Die Hard》中的一句话:"当亚历山大看到他的领土辽阔时,他为没有更多的世界需要征服而哭泣",并质疑.NET的性能改进是否类似.没有更多的“性能”世界需要征服吗?我有点头晕目眩地说,即使.NET6很快, .NET7明确地强调了我们还可以做得更多,并且已经做得更多。

与之前版本的.NET一样,性能是贯穿整个技术栈的一个关键焦点,性能是贯穿整个栈的关键焦点,无论是为性能而明确创建的特性,还是在设计和实现时仍然牢记性能的与性能无关的特性.现在,一个.NET7发行版的候选版本即将到来,这是讨论它的好时机. 

在过去的一年中,每次我回顾可能对性能产生积极影响的提交,我都会将该链接复制到我为撰写本文而维护的期日记中.几周前,当我坐下来写这篇文章时,我面临着一份近1000个影响性能的PRs的列表(在发布的7000多个PRs中),我很高兴在这里与大家分享其中的近500个(.Net 6有400左右影响性能的提交).

.Net7很快,非常快.这个版本的运行时和核心库中有上千个影响性能的PRs,更不用说Asp.Net Core和WinForm和Entity Framework Core 性能改进.目前来说.Net 7是.Net中最快的.如果你的经理问你为什么你的项目应该升级到.Net 7,你可以说"除了发布版中的所有新功能,.Net 7的速度超级快"

我希望每一个有兴趣的人在离开这篇文章时都能对.NET是如何实现的,为什么做出了各种决策,评估了哪些权衡,采用了哪些技术,考虑了哪些算法,以及使用了哪些有价值的工具和方法,使.NET比以前更快.我希望开发人员从我们自己的学习中学习,并找到将这些新发现的知识应用于他们自己的代码库的方法,从而进一步提高生态系统中代码的整体性能.我希望开发人员多做一点,考虑下一次在处理棘手问题时使用分析器,考虑查看他们正在使用的组件的源代码,以便更好地理解如何使用它,并考虑重新审视以前的假设和决策,以确定它们是否仍然准确和适当.我希望开发人员对提交PRs以改进.NET的前景感到兴奋,不仅是为了他们自己,也是为了全球使用.NET的每个开发人员.如果其中任何一个听起来很有趣,那么我鼓励你选择最后一次冒险: 准备一瓶你最喜欢的热饮,舒适地享受,并请享受.
 

有哪些性能改进

.Net 7性能改进,有JIT和NativeAOT/GC/反射等

准备工作

创建一个性能测试的项目:
#创建项目
dotnet new console -o net7perf

#进入项目
cd .\net7perf\

#使用BenchmarkDotNet进行性能测试
dotnet add package benchmarkdotnet

修改项目工程文件:

<Project Sdk="Microsoft.NET.Sdk">

	<PropertyGroup>
		<OutputType>Exe</OutputType>
		<!--测试.Net6和.Net 7-->
		<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
		<ImplicitUsings>enable</ImplicitUsings>
		<Nullable>enable</Nullable>
		<!--使用CSharp语言的预览版本-->
		<LangVersion>Preview</LangVersion>
		<!--允许使用不安全操作,如指针-->
		<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
		<!--指定GC的模式为服务器模式-->
		<ServerGarbageCollection>true</ServerGarbageCollection>
	</PropertyGroup>

	<ItemGroup>
		<PackageReference Include="benchmarkdotnet" Version="0.13.2.1879" />
	</ItemGroup>

</Project>

调整Program.cs代码:

using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using Microsoft.Win32;
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.IO.MemoryMappedFiles;
using System.IO.Pipes;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Security;
using System.Net.Sockets;
using System.Numerics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics;
using System.Security.Authentication;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;

[MemoryDiagnoser(displayGenColumns: false)]
[DisassemblyDiagnoser]
[HideColumns("Error", "StdDev", "Median", "RatioSD")]
public partial class Program
{
    static void Main(string[] args) => BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);

    //这里将测试代码拆分具体文件中
}
#运行测试
dotnet run -c Release -f net6.0 --filter '*方法名*' --runtimes net6.0 net7.0

后面着重翻译JIT,因为JIT是直接影响程序的性能.

秋风 2022-09-05