共计 14547 个字符,预计需要花费 37 分钟才能阅读完成。
.NET 8 是一个长期反对 (LTS) 版本。这篇文章涵盖了推动加强性能优先级排序和抉择开发的次要主题和指标。.NET 8 预览版和公布候选版本将每月交付一次。像平常一样,最终版本将在 11 月的某个时候在 .NET Conf 上公布。
.NET 版本包含产品、库、运行时和工具,代表 Microsoft 内外多个团队之间的合作。这篇博文中涵盖的更宽泛的主题并不蕴含 .NET 8 的所有要害场景和投资。它们代表了很大的畛域,但只是进入 .NET 8 的所有重要工作的一部分。咱们打算对 ASP.NET Core, Blazor, EF Core, WinForms, WPF 和其余平台进行宽泛的投资。
欢送应用 .NET 8
去年年底,咱们公布了 .NET 7,这是 .NET 团队与反对该版本的令人惊叹的社区单干的后果,该版本有 10,000 多名社区成员提供了超过 28,000 个社区奉献。.NET 7 是当今构建应用程序的首选框架。该版本将平台与对 ARM64 的原生反对和对 Linux 的加强反对对立起来。它有助于通过 .NET MAUI 等工具使您的应用程序现代化,这些工具能够从同一代码库构建跨平台的挪动和桌面应用程序。它包含对 API 性能的改良,并使构建和部署分布式云原生应用程序变得更加容易。. NET 7 通过改良 C# 11 缩小了必要的代码量,简化了构建应用程序的体验,并使得仅用几行代码就能够创立和配置 API。从帮忙调试云 API 集成到间接从 .NET SDK 构建容器的开发隧道,对工具进行了大量改良,帮忙开发人员进步工作效率。
咱们将在整个版本中更新 .NET 8 中的新增性能。
您能够通过向下滚动浏览咱们在预览 1 中公布的内容。首先,让咱们瞻望一下 .NET 8 的愿景。
云原生开发者的最佳平台和工具
咱们置信 .NET 开发人员应该可能将他们的应用程序疾速迁徙到云中,在不影响性能的状况下扩大他们的应用程序,并依据可操作的数据和对于您的应用程序在生产中的反馈来改良他们的应用程序。咱们将投资于通过继续集成和部署更轻松地治理本地开发和测试的残缺端到端体验。咱们的指标是让微服务架构的施行以及容器的构建和部署变得更加容易。
云原生是一个术语,用于形容专门为在云计算环境中部署而构建的应用程序的架构和设计。云原生背地的次要思维是利用云计算平台提供的劣势,例如可扩展性、弹性和自我修复,来创立高度可扩大和有弹性的应用程序。这提供了灵活性,并防止了为反对增长而对硬件和软件进行潜在的适度投资。许多开发人员将云原生与微服务、容器编排 (Kubernetes) 和“即服务”产品等概念分割在一起。
应用 MAUI 和 Blazor 混合进行跨平台挪动和桌面开发的绝佳体验
在 .NET 7 期间,咱们公布了 .NET 多平台应用程序用户界面 (MAUI) SDK 和 Visual Studio 工具反对。.NET MAUI 提供了一个框架,用于应用单个 C# 代码库为运行 Android、iOS、macOS 和 Windows 的挪动和桌面设施创立本机应用程序。除了反对 XAML UI 之外,您还能够应用 Blazor 构建具备 Razor UI 组件的混合应用程序,这些应用程序能够拜访本机设备平台并在挪动、桌面和 Web 之间共享。.NET 团队打算以这些教训为根底,专一于进步 SDK 和工具的品质、稳定性、性能和集成度。
势头:依据您的意见持续关注品质和性能
.NET 的每个版本都包含对 API、库和框架的性能、品质、稳定性和易用性的改良,它们形成了沉闷且一直倒退的 .NET 生态系统。其中许多改良是由客户和社区成员确定并优先思考的。.NET 8 将遵循雷同的趋势,依附您高度重视的反馈来帮忙领导咱们的愿景并推动咱们的重点。
理解最新状况并放弃最新状态
.NET 降级帮忙是一个有价值的工具,能够帮忙开发人员将他们的应用程序从旧版本的 .NET Framework 迁徙到新版本。该工具的最新版本具备改良的性能,能够反对新场景并解决更多案例。有了这个工具,开发人员当初能够轻松地将他们的应用程序降级到 .NET 6 或 .NET 7。
该工具能够自动检测并倡议须要对代码进行的更改,以确保与较新版本的框架兼容。此外,它还能够解决更简单的场景,例如降级应用第三方库的应用程序以及与更新的平台性能集成。这些改良使 .NET 降级辅助成为那些心愿放弃其应用程序最新并利用最新的 .NET 性能的开发人员的不可或缺的工具。该工具最近作为 Visual Studio 扩大引入。可帮忙您从舒服的 Visual Studio 降级。
以 .NET 8 为指标
要以 .NET 8 为指标,您首先须要确保从 Microsoft 官方网站装置了 .NET 8 SDK。接下来,您能够创立一个新我的项目,并通过在我的项目设置中设置适当的指标框架来指定您心愿以 .NET 8 为指标。
您还能够通过更改我的项目属性中的指标框架,将现有我的项目更新为面向 .NET 8。为此,请在 Visual Studio 或您喜爱的 IDE 中右键单击我的项目,抉择“属性”,而后抉择“应用程序”选项卡。从那里,您能够抉择要应用的指标框架版本。这将设置适当的指标框架:
<TargetFramework>net8.0</TargetFramework>
请记住,以 .NET 8 为指标可能须要更改您的代码或依赖项,因为 API 或其余性能可能与以前版本的 .NET 有所不同。最好查看 .NET 8 的文档和发行阐明,以确保您的代码和依赖项与新版本兼容。
.NET 8 预览版 1 中的新增性能
咱们的第一个预览版蕴含您明天就能够试用的新性能。以下是预期后果的摘要。无关具体的发行阐明和重大更改,请浏览 .NET 8 中的新增性能。
Native AOT
第一个 NativeAOT 性能在 .NET 7 和指标控制台应用程序中公布。Ahead-of-Time (AOT) 编译是 .NET 中的一项重要性能,能够对 .NET 应用程序的性能产生重大影响。感激 Adeel 和 Filip 将 NativeAOT 性能引入 macOS 进行预览 1。.NET 团队将专一于欠缺 .NET 8 的一些基础知识,例如大小(请参阅 dotnet/runtime#79003)。应用 NativeAOT 公布应用程序会创立一个齐全独立的应用程序版本,不须要独自的运行时,因为所有内容都蕴含在单个文件中。从预览版 1 开始,这个文件变小了。事实上,Linux 版本当初最多放大了 50%。
以下是蕴含整个 .NET 运行时的 Native AOT 的“Hello, World”应用程序的大小:
NativeAOT 将持续扩大并瞄准 .NET 8 中的其余利用场景,因而请持续关注此博客以获取将来更新!
如果您不相熟 AOT,这里有一些 AOT 提供的益处:
- 缩小内存占用 :与 JIT 编译代码相比,AOT 编译代码须要更少的内存,因为 JIT 编译器生成 AOT 编译应用程序不须要的中间代码。这对于内存无限的设施尤其无益,例如嵌入式零碎和挪动设施。
- 改良的启动工夫 :与 JIT 编译代码相比,AOT 编译代码启动速度更快,因为它打消了 JIT 编译器生成中间代码并针对特定硬件和软件环境优化代码的须要。这对于必须疾速启动的应用程序尤其无利,例如零碎服务、无服务器“性能”和后台任务。
- 缩短电池寿命 :与 JIT 编译代码相比,AOT 编译代码耗费的电量更少,因为它打消了 JIT 编译器生成中间代码并针对特定硬件和软件环境优化代码的须要。这对于依赖电池的设施(例如挪动设施)尤其无益。
.NET 容器镜像
.NET 开发人员能够应用容器镜像以轻量级、可移植的格局打包和部署他们的应用程序,这种格局能够在不同环境中运行并且能够轻松部署到云端中。对于如何将容器镜像用于 .NET 应用程序,预览版 1 做出了以下改良:
- 将默认 Linux 发行版更新为 Debian 12:.NET 容器镜像当初应用 Debian 12 (Bookworm),咱们预计将在 2023 年年中公布。Debian 用于不便的标签,8.0 如 8.0-bookworm-slim。
- 标签更改 :.NET 8 预览容器镜像将应用 8.0-preview 作为标签(不是 8.0)并在 Release Candidate 版本过渡到 8.0。这种办法的指标是更分明地形容预览版。这是依据社区申请进行的更改。
- 与非根(non-root)用户一起运行容器镜像 :只管容器根底镜像简直总是配置为与根用户一起运行——这种设置往往会保留在生产环境中——但它并不总是最好的办法。然而,将每个应用程序配置为领有不同的用户是一件很苦楚的事件,而且容器镜像不会附带适宜容器工作负载的非根用户。
.NET 8 提供了一种更好的办法。从预览版 1 开始,咱们公布的所有容器镜像都将反对非根配置。以下是用于以非根身份为 Dockerfiles 运行容器的单行示例:
USER app
此外,您当初能够应用 -u app。默认端口已从端口 80 更改为 8080。这是启用非根计划所必须的重大更改,因为端口 80 是特权端口。
运行时和库
解决随机性的实用办法
System.Random 和 System.Security.Cryptography.RandomNumberGenerator 都有实用办法 GetItems 以用于从输出集中随机抉择我的项目(“用替换”),以及用于随机化跨度程序的实用办法 Shuffle。
Shuffle 有助于缩小机器学习中的训练偏差(因而第一件事并不总是训练,最初一件事总是测试):
YourType[] trainingData = LoadTrainingData();
Random.Shared.Shuffle(trainingData);
IDataView sourceData = mlContext.Data.LoadFromEnumerable(trainingData);
DataOperationsCatalog.TrainTestData split = mlContext.Data.TrainTestSplit(sourceData);
model = chain.Fit(split.TrainSet);
IDataView predictions = model.Transform(split.TestSet);
...
咱们玩个游戏好吗?玩西蒙游戏怎么样?
private static ReadOnlySpan<Button> s_allButtons = new[]
{
Button.Red,
Button.Green,
Button.Blue,
Button.Yellow,
};
...
Button[] thisRound = Random.Shared.GetItems(s_allButtons, 31);
// rest of game goes here ...
System.Numerics 和 System.Runtime.Intrinsics
在可能的状况下,咱们将 Vector256<T> 从新实现为外部 2x Vector128<T> ops:dotnet/runtime#76221。这能使一些函数局部减速,例如在 Arm64 上 Vector128.IsHardwareAccelerated == true 但 Vector256.IsHardwareAccelerated == false。
咱们增加了 Vector512<T> 初始托管实现:dotnet/runtime#76642。与之前的工作项十分类似,这在外部实现为 2x Vector256<T> ops(因而间接实现为 4x Vector128 ops)。这能使一些函数局部减速,即便 Vector512.IsHardwareAccelerated == false 留神:Vector512 还没有间接减速,即便底层硬件反对它也是如此。此类性能应在将来的预览版中启用。
重写 Matrix3x2 和 Matrix4x4 以更好地利用硬件加速:dotnet/runtime#80091。这能使某些基准测试的性能晋升高达 48 倍。6-10 倍的改良更为常见。
留神:预览版 2 会对 Quaternion 和 Plane 进行改良。
Hardware Intrinsics 当初用 ConstExpected 属性进行正文:dotnet/runtime#80192。这能确保用户晓得底层硬件何时须要常量,因而十分量值何时可能会意外侵害性能。
将 Lerp API 增加到 IFloatingPointIeee754<TSelf> 从而增加到 float (System.Single), double (System.Double) 和 System.Half 和: dotnet/runtime#81186。这能无效且正确地执行两个值之间的线性插值。
JSON 改良
咱们不断改进 System.Text.Json,专一于加强源代码生成器在 NativeAOT 应用程序中与 ASP.NET Core 一起应用时的性能和可靠性。下表显示了预览版 1 附带的新性能:
- 短少成员解决 dotnet/runtime#79945
当初能够配置对象反序列化行为,底层 JSON 负载蕴含无奈映射到反序列化 POCO 类型成员的属性时都能够实用。这能够通过设置一个 JsonUnmappedMemberHandling 值来管制,也能够作为 POCO 类型自身的正文,全局上 JsonSerializerOptions 或通过自定义 JsonTypeInfo 相干类型的合同以编程形式进行管制:
JsonSerializer.Deserialize<MyPoco>("""{"Id": 42,"AnotherId": -1}""");
// JsonException : The JSON property 'AnotherId' could not be mapped to any .NET member contained in type 'MyPoco'.
[JsonUnmappedMemberHandling(JsonUnmappedMemberHandling.Disallow)]
public class MyPoco
{public int Id { get; set;}
}
- 源生成器反对 required 和 init 属性 dotnet/runtime#79828
源生成器当初反对序列化具备 required 和 init 属性的类型,正如以后在基于反射的序列化中所反对的那样。 - 接口层次结构反对 dotnet/runtime#78788
System.Text.Json 当初反对从接口层次结构序列化属性:
IDerived value = new Derived {Base = 0, Derived =1};
JsonSerializer.Serialize(value); // {"Base":0,"Derived":1}
public interface IBase
{public int Base { get; set;}
}
public interface IDerived : IBase
{public int Derived { get; set;}
}
public class Derived : IDerived
{public int Base { get; set;}
public int Derived {get; set;}
}
- Snake Case 和 Kebab Case dotnet/runtime#69613
该库当初附带了 snake_case 的命名策略和 kebab-case 属性名称转换。它们的用法与现有的 camelCase 命名策略相似:
var options = new JsonSerializerOptions {PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower};
JsonSerializer.Serialize(new { PropertyName = "value"}, options); // {"property_name" : "value"}
当初能够应用以下命名策略:
namespace System.Text.Json;
public class JsonNamingPolicy
{public static JsonNamingPolicy CamelCase { get;}
public static JsonNamingPolicy KebabCaseLower {get;}
public static JsonNamingPolicy KebabCaseUpper {get;}
public static JsonNamingPolicy SnakeCaseLower {get;}
public static JsonNamingPolicy SnakeCaseUpper {get;}
}
感激 @YohDeadfall 奉献了施行。
- 增加 JsonSerializer.MakeReadOnly() 和 IsReadOnly API dotnet/runtime#74431JsonSerializerOptions 类始终应用可解冻语义,但直到现在解冻只能通过将实例传递给其中一种 JsonSerializer 办法来隐式实现。增加新 API 后,用户能够明确管制何时 JsonSerializerOptions 应解冻其实例:
public class MySerializer
{private JsonSerializerOptions Options { get;}
public MySerializer()
{Options = new JsonSerializerOptions(JsonSerializerDefaults.Web) {Converters = { new MyCustomConverter() } };
Options.MakeReadOnly(); // Make read-only before exposing the property.}
}
外围库中以性能为核心的全新类型
多个新类型已增加到外围库中,开发人员可能利用新类型在常见场景中进步代码的性能。
新的命名空间 System.Collections.Frozen 提供 FrozenDictionary<TKey, TValue> 和 FrozenSet<T> 汇合。这些类型提供了一个不可变的外表区域,一旦创立,键或值就不能够进行任何更改。这反过来又使汇合可能依据提供的数据更好地优化后续读取操作(例如 TryGetValue),从而使其可能在结构期有更多工夫来优化所有将来的拜访。这对于第一次应用时填充、且需在长期服务期间继续存在的汇合特地有用,例如:
private static readonly FrozenDictionary<string, bool> s_configurationData =
LoadConfigurationData().ToFrozenDictionary(optimizeForReads: true);
...
if (s_configurationData.TryGetValue(key, out bool setting) && setting)
{Process();
}
现有类型 ImmutableArray<T>.Builder 还取得了一种将其内容高效转换为 ImmutableArray<T> 的新办法。.NET 8 引入了 DrainToImmutable(),它将以后内容作为不可变数组返回,并将构建器的汇合重置为零长度数组,它会抉择最无效的办法来执行此操作。基于元素的计数,咱们能够应用此办法代替有条件地调用 ToImmutable() 或 MoveToImmutable()。
新类型的另一个例子是 IndexOfAnyValues<T>,它能帮忙开发人员事后投入一些工夫以换取当前更快的执行速度。除了像 IndexOfAnyInRange 之类的新办法之外,还增加了承受 IndexOfAnyValues<T> 实例的新重载 IndexOfAny,能够创立实例来示意要搜寻的一组 T 值。此实例的创立解决派生任何必要的数据以优化后续搜寻。例如,如果您常常搜寻所有 ASCII 字母和数字以及一些标点符号字符,您之前可能会这样写:
private static readonly char[] s_chars = "-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz".ToCharArray();
...
int i = str.IndexOfAny(s_chars);
然而,这要求没有任何类型的向量化可能进步搜寻效率,要么须要在每次调用 IndexOfAny 时花工夫计算必要的状态以减速操作。当初,您能够这样写:
private static readonly IndexOfAnyValues<char> s_chars = IndexOfAnyValues.Create("-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz");
...
int i = str.AsSpan().IndexOfAny(s_chars);
事后计算所有该状态一次,以便在每次后续调用时都能够重用 IndexOfAny。
新类型 CompositeFormat 会本人重复这种模式。.NET 长期以来始终反对通过 API 进行字符串格式化,例如 string.Format 和 StringBuilder.AppendFormat,例如:
static string GetMessage(int min, int max) =>
string.Format(CultureInfo.InvariantCulture, "Range from {0} to {1}", min, max);
C# 6 增加了对字符串插值的反对,而后 C# 10 联合 .NET 6 显著进步了这些操作的效率,使得雷同的操作能够写成:
static string GetMessage(int min, int max) =>
string.Create(CultureInfo.InvariantCulture, $"Range from {min} to {max}");
然而它是在编译时而不是在每次调用 string.Format 时执行能够事后计算的工作。而这须要在编译时就能获取到格局字符串,以便能够在编译时对其进行解析……如果它直到运行时才获取到怎么办,例如,如果它是从资源文件或其余动静形式加载的?为此,.NET 8 增加了 CompositeFormat 类型。与 IndexOfAnyValues<T> 一样,它能够执行每次应用时须要执行的操作,而后将其取出执行一次。
private static readonly CompositeFormat s_rangeMessage = CompositeFormat.Parse(LoadRangeMessageResource());
...
static string GetMessage(int min, int max) =>
string.Format(CultureInfo.InvariantCulture, s_rangeMessage, min, max);
这些新的重载还反对泛型参数,以防止装箱开销(boxing overheads)将所有内容都辨认为 object。
.NET 8 预览版 1 还减少了对新的以性能为核心的哈希算法的反对,包含新的 XxHash3 和 XxHash128 类型,它们提供了疾速 XXH3 和 XXH128 哈希算法的实现。
.NET SDK
dotnet publish 与 dotnet pack 默认生产 Release 资产
Publish(公布)和 Pack(打包)动词的目标是产生生产资产,这意味着它们应该生产 Release 资产。在 .NET 8 中,他们将默认执行此操作。
此性能由 PublishRelease 和 PackRelease 布尔属性管制。默认为 true。
用 dotnet publish 演示该性能最简略:
/app# dotnet new console
/app# dotnet build
app -> /app/bin/Debug/net8.0/app.dll
/app# dotnet publish
app -> /app/bin/Release/net8.0/app.dll
app -> /app/bin/Release/net8.0/publish/
/app# dotnet publish -p:PublishRelease=false
app -> /app/bin/Debug/net8.0/app.dll
app -> /app/bin/Debug/net8.0/publish/
请留神,PublishRelease 并且 PackRelease 也存在于从 7.0.200 SDK 开始的 .NET 7 中。它们在 .NET 7 中是可选的,并且必须设置 true 能力执行雷同的行为。
请参阅重大更改相干文档:
- dotnet publish
- dotnet pack
Linux 反对
从 dotnet/dotnet 构建您本人的 .NET
.NET 当初能够间接从 dotnet/dotnet 存储库在 Linux 上构建。它应用 dotnet/source-build 构建 .NET 运行时、工具和 SDK。例如,这与 Red Hat 和 Canonical 用于构建 .NET 的构建雷同。随着工夫的推移,咱们将扩大其性能以反对 macOS 和 Windows。
请参阅构建阐明以在您本人的计算机上构建 VMR。对于许多人来说,在容器中构建是最简略的办法,因为咱们的 dotnet-buildtools/prereqs 容器镜像蕴含所有必须的依赖项。
咱们称这个新存储库为 Virtual Mono Repository (VMR)。它具备真正的 monorepo 的劣势,这多亏了开发者们每天在泛滥现有存储库中(更无效地)所做的定期更新。咱们置信,VMR 和更小的“工作存储库”之间的拆散是 .NET 我的项目的将来。咱们心愿在 VMR 中更容易构建横切性能,然而,咱们目前还没有实现。
从源代码构建 .NET 并将其构建成一个残缺产品是可行的,咱们认为这个新办法就是咱们向其迈出的重要一步。
在 .NET 8 之前,从源构建是可行的,但须要从与公布版本绝对应的 dotnet/installer commit 提交创立“source tarball”。您不再须要进行这一操作。存储库将有与每个公布版本对应的标签,以及继续跟踪产品状态的 main 和 release/8.0-previewN 分支。
.NET 8 + Ubuntu Chiseled 容器镜像
咱们正在公布装置了 .NET 8 的 Ubuntu Chiseled 镜像. 相比惯例容器,这种类型的镜像实用于心愿应用有设施式计算劣势的开发人员。咱们预计,当 .NET 8 上线时,Canonical 和 Microsoft 都将反对 Ubuntu chiseled 镜像。
咱们打算从 .NET 8 开始,公布以 Ubuntu Chiseled 模式的 dotnet/monitor 镜像。值得一提的是,monitor 镜像是咱们公布的生产利用镜像。
Chiseled images 有多种劣势:
- 超小图像(减小尺寸和攻击面)
- 没有包管理器(防止整类攻打)
- 没有 shell 外壳(防止整类攻打)
- 没有 root(防止整类攻打)
您能够由此 aspnetapp sample 查看生产中的的 Chiseled 容器镜像。应用时,您只须要更改一行代码。
.NET 6 和 .NET 7 版本的 Chiseled 镜像当初已被公布到 nightly 存储库中。
Linux 反对和基线指标
咱们正在更新反对 .NET 8 的 Linux 零碎的最低基线。有三个变动须要留神。
- .NET 产品将针对 Ubuntu 16.04 版本进行构建,实用于所有体系结构。这对于定义 .NET 8 所需最低的 glibc 版本十分重要。例如,因为此项更改,.NET 8 将甚至无奈在 Ubuntu 14.04 上启动。
- 对于 Red Hat Enterprise Linux(RHEL),咱们将反对 RHEL 8+,启用 RHEL 7。
- 咱们只会公布 RHEL 的反对申明,然而,咱们心愿也能反对其余 RHEL ecosystem distros 生态系统发行版。
重大变动次要就这些。咱们仍将反对在 Arm32、Arm64 和 x64 架构上根底上应用 Linux。
请留神,这些更改仅实用于 Microsoft 外部版本。应用 source-build 构建的不同组织可能状况不同,通常为了一个构建生成构建版本仅实用于一个发行版版本,例如 Ubuntu 24.04。
上面演示了 Ubuntu 16.04 glibc 版本以及其用于其余发行版的模式。
$ docker run --rm ubuntu:16.04 ldd --version
ldd (Ubuntu GLIBC 2.23-0ubuntu11.3) 2.23
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.
代码的生成
社区 PRs (非常感谢 JIT 论坛的 contributors!)
- @am11 更新了 CLRConfiguration 和 jithost 中的 env 变量 PR#77025。
- @En3Tho 将 (X & 1) != 0 优化为 (X & 1) 和 (X & 1) == 0 以及 ((NOT X) & 1) in PR#74806, 并修复了与 faulty LIR range 相干的漏 PR#77166。
- @MichalPetryka 实现了 Type.IsEnum 和 Type.GetEnumUnderlyingType 在 PR#71685 的外部函数,并将 MemoryMarshal.GetArrayDataReference 转换为 JIT 外部函数 PR#79760。
- @pedrobsaila 在 PR#62689 中做出了第一个 PR 奉献,收回无分支表单从 (x >= 0 && y >= 0) 到 (x | y) >= 0,从 (x != 0 && y != 0) 到 (x | y) != 0。
- @a74nh, @AndyJGraham and @swapnilGaikwad 对 Arm64 性能改良做出了奉献(请参阅 Arm64 局部)。
- @DeepakRajendrakumaran 为 AVX-512 做出了奉献(见 AVX-512 局部)。
- @SingleAccretion 为预览版本 1 进行了 72 个拉取申请 72 PR contributions 其中有:
1.PR#72719 优化的内存加载 / 在强制转换下存储
2.PR#77238 和 PR#76139 是与 SSA 相干的改良
3.PR#78246 通过删除 ADDR 节点简化 JIT IR
4.PR#77990 优化固定存储
云原生
- PR#79709 删除了非 GC 动态字段的帮忙程序调用,PR#80969 优化了 GC 类型的动态字段。
- PR#80831 对单态案例实现将强制转换到接口进行非虚拟化。
Arm64
Arm64 性能改良工作正在按计划进行 Issue#77010。
- @AndyJGraham and @a74nh 施行了与 ldp 和 stp 相干的窥视孔优化 PR#77540
- @a74nh 在 PR#73472, PR#77728, PR#78223, 和 PR#77888 中启用‘If Conversion’
- @swapnilGaikwad 在条件抉择中应用零寄存器 (csel) PR#78330
- @SwapnilGaikwad 在 PR#79550 启用 mneg , 多抉择中的一项 (Issue#68028)
- 通过比拟 PR#75864 和 PR#75999 得出更快的矢量
- PR#75823 增加了对 Arm64 上的“移位寄存器”操作的反对
AVX-512
- .NET 8 将按计划反对 AVX-512 ISA 扩大 Issue#77034.
- PR#76642 实现了 API, 公开 Issue#73262 中 Vector512<T> 类型
- 虚拟机中增加 AVX-512 状态已通过 @DeepakRajendrakumaran 的批准收到反对 PR#74113
- @DeepakRajendrakumaran 增加了对 emitOutput 输入 门路的 EVEX 编码反对 PR#75934, PR#77419 和 PR#78044
- JitInterface 已由 @DeepakRajendrakumaran 更新为 Vector512 PR#81197
个别 SIMD 改良
- PR#77562 为在 Issue#76593 定义的 Vector64/128/256/512<T> 和 Vector<T> 上新批准的 API 施行了额定的外部函数
- PR#79720 应用 HWIntrinsics 实现 Vector2/3/4 和 Vector<T>
- PR#77947 为 OrdinalIgnoreCase 矢量化 String.Equals
PGO
PGO 的根本改良正在按计划进行中 Issue#74873。
- 引入了新的 JIT 层,以仅检测热 Tier0 和 R2R 代码。这意味着您不再须要禁用 ReadyToRun 并就义启动工夫来取得齐全 PGO 级别的性能劣势:PR#70941
- PR#80481 为所有场景启用了基于边缘的配置文件
- 构建预测列表已移至 JIT 的晚期阶段:
PR#80625, PR#80856, PR#81288, PR#81246, PR#81196, PR#81000, 和 PR#80891。
循环优化
- PR#75140 在循环克隆中反对委托 GDV guards
- PR#80353 扩大循环展开优化
个别优化
@SingleAccretion 在 PR#76263 Long 中启用了 32 位解锁字段注册上的多注册变量晋升。
- PR#77103 施行了 Issue#8795 中提出的新尾部合并优化
- PR#81055 确保 Span<T>.Length 和 ROSpan<T>.Length 被辨认为“never negative”
- PR#79346 增加了一个晚期的活跃度传递,容许 JIT 在传递构造参数时删除大量不必要的构造正本
- PR#77874 删除了一些波及小整数类型的简略操作的不必要的零 / 符号扩大指令
- 字符串文字、typeof()、动态字段通过 PR#49576, PR#75573 和 PR#76112
1. 容许 JIT 在某些状况下省略 GC 写阻碍 PR#76135
2.typeof(..) 在大多数状况下不再须要助手调用,例如:
Type GetMyType() => typeof(string);
; Method MyType():System.Type:this
3.4883EC28 sub rsp, 40
4.48B918083857FC7F0000 mov rcx, 0x7FFC57380818
5.E80DE8AB5F call CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE
6.90 nop
7.4883C428 add rsp, 40
8.48B8B800000364020000 mov rax, 0x264030000B8 ;‘System.String’C3 ret -; Total bytes of code: 25 +; Total bytes of code: 11
- 动态和动态只读字段的一批改
进 PR#77102, PR#77593, PR#77354, PR#77737, PR#78593, PR#78736 and PR#78783
- PR#81005 中显示的表达式就是一个很好的例子。JIT 当初可能在.NET 8 中折叠应用
JIT 吞吐量改良
- PR#80265 将 JitHashTable 迭代转换为基于范畴的迭代 for,将吞吐量进步了 0.22%
总之,.NET 8 预览版 1 的公布是 Microsoft 多元化工程师团队与高度参加的开源社区之间良好合作的证实。.NET 8 中的新性能和改良是社区成员辛勤努力和贡献的成绩,咱们非常感谢大家做出的奉献。
该社区器重包容性和多样性,能成为其中的一员,咱们很骄傲。咱们致力于建设一个人人都能够拜访的技术生态系统。咱们置信,只有咱们一起致力,就能够获得平凡的胜利,咱们对 .NET 的将来充斥期待。
点我浏览原博客,获取更多具体内容和相干链接~