点击上方蓝字
关注我们
(本文阅读时间:20分钟)
.NET 版本包括产品、库、运行时和工具,代表 Microsoft 内外多个团队之间的协作。这篇博文中涵盖的更广泛的主题并不包含 .NET 8 的所有关键场景和投资。它们代表了很大的领域,但只是进入 .NET 8 的所有重要工作的一部分。我们计划对 ASP.NET Core, Blazor, EF Core, WinForms, WPF 和其他平台进行广泛的投资。
欢迎使用 .NET 8
您可以通过向下滚动阅读我们在预览1中发布的内容。首先,让我们展望一下 .NET 8 的愿景。
云原生是一个术语,用于描述专门为在云计算环境中部署而构建的应用程序的架构和设计。云原生背后的主要思想是利用云计算平台提供的优势,例如可扩展性、弹性和自我修复,来创建高度可扩展和有弹性的应用程序。这提供了灵活性,并避免了为支持增长而对硬件和软件进行潜在的过度投资。许多开发人员将云原生与微服务、容器编排 (Kubernetes) 和“即服务”产品等概念联系在一起。
在 .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 8 为目标
<TargetFramework>net8.0</TargetFramework>
.NET 8 预览版 1 中的新增功能
我们的第一个预览版包含您今天就可以试用的新功能。以下是预期结果的摘要。有关详细的发行说明和重大更改,请阅读 .NET 8 中的新增功能。
减少内存占用 :与 JIT 编译代码相比,AOT 编译代码需要更少的内存,因为 JIT 编译器生成 AOT 编译应用程序不需要的中间代码。这对于内存有限的设备尤其有益,例如嵌入式系统和移动设备。 改进的启动时间 :与 JIT 编译代码相比,AOT 编译代码启动速度更快,因为它消除了 JIT 编译器生成中间代码并针对特定硬件和软件环境优化代码的需要。这对于必须快速启动的应用程序尤其有利,例如系统服务、无服务器“功能”和后台任务。 延长电池寿命 :与 JIT 编译代码相比,AOT 编译代码消耗的电量更少,因为它消除了 JIT 编译器生成中间代码并针对特定硬件和软件环境优化代码的需要。这对于依赖电池的设备(例如移动设备)尤其有益。
▌.NET 容器镜像
将默认 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) 用户一起运行容器镜像 :尽管容器基础镜像几乎总是配置为与根用户一起运行——这种设置往往会保留在生产环境中——但它并不总是最好的方法。然而,将每个应用程序配置为拥有不同的用户是一件很痛苦的事情,而且容器镜像不会附带适合容器工作负载的非根用户。
USER app
此外,您现在可以使用 -u app。默认端口已从端口80更改为8080。这是启用非根方案所必需的重大更改,因为端口80是特权端口。
➤ 处理随机性的实用方法
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
➤ JSON 改进
缺少成员处理 dotnet/runtime#79945
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
接口层次结构支持 dotnet/runtime#78788
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
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; }
}
添加 JsonSerializer.MakeReadOnly() 和 IsReadOnly API dotnet/runtime#74431
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.
}
}
➤ 核心库中以性能为中心的全新类型
private static readonly FrozenDictionary<string, bool> s_configurationData =
LoadConfigurationData().ToFrozenDictionary(optimizeForReads: true);
...
if (s_configurationData.TryGetValue(key, out bool setting) && setting)
{
Process();
}
private static readonly char[] s_chars = "-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz".ToCharArray();
...
int i = str.IndexOfAny(s_chars);
private static readonly IndexOfAnyValues<char> s_chars = IndexOfAnyValues.Create("-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz");
...
int i = str.AsSpan().IndexOfAny(s_chars);
static string GetMessage(int min, int max) =>
string.Format(CultureInfo.InvariantCulture, "Range from {0} to {1}", min, max);
static string GetMessage(int min, int max) =>
string.Create(CultureInfo.InvariantCulture, $"Range from {min} to {max}");
private static readonly CompositeFormat s_rangeMessage = CompositeFormat.Parse(LoadRangeMessageResource());
...
static string GetMessage(int min, int max) =>
string.Format(CultureInfo.InvariantCulture, s_rangeMessage, min, max);
.NET 8 预览版 1 还增加了对新的以性能为中心的哈希算法的支持,包括新的 XxHash3 和 XxHash128 类型,它们提供了快速 XXH3 和 XXH128 哈希算法的实现。
➤ dotnet publish 与 dotnet pack默认生产 Release 资产
/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/
dotnet publish
dotnet pack
https://learn.microsoft.com/dotnet/core/compatibility/sdk/8.0/dotnet-pack-config
▌Linux 支持
➤ 从 dotnet/dotnet 构建您自己的 .NET
构建说明
超小图像(减小尺寸和攻击面) 没有包管理器(避免整类攻击) 没有shell外壳(避免整类攻击) 没有 root(避免整类攻击)
.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 生态系统发行版。
$ 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.
▌代码的生成
@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 其中有:
PR#79709 删除了非 GC 静态字段的帮助程序调用, PR#80969 优化了 GC 类型的静态字段。 PR#80831 对单态案例实现将强制转换到接口进行非虚拟化。
@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 上的“移位寄存器”操作的支持
.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
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
引入了新的 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 扩展循环展开优化
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
Type GetMyType() => typeof(string);
; Method MyType():System.Type:this
-; 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 中折叠使用
PR#80265 将 JitHashTable 迭代转换为基于范围的迭代for,将吞吐量提高了 0.22%
总之,.NET 8 预览版1的发布是 Microsoft 多元化工程师团队与高度参与的开源社区之间良好协作的证明。.NET 8 中的新功能和改进是社区成员辛勤努力和奉献的成果,我们非常感谢大家做出的贡献。