原文: [A Dive into .Net 8 Native AOT and Efficient Web Development]

作者: [sharmila subbiah]

引言

随着 .NET 8 的发布,微软迈出了重要一步,为 ASP.NET Core 引入了原生的 Ahead-of-Time (AOT) 编译。这一进步不仅提高了应用程序的性能,还简化了开发过程,标志着 .NET 生态系统进入了新的时代。

.NET 8中原生AOT的出现

.NET 8 引入了原生 AOT,这对 Web 开发人员来说是一个重大改变。该技术将 .NET 代码直接编译为原生代码,无需在运行时进行即时 (JIT) 编译。结果如何?启动时间更快、内存占用更少、以及整体改善的应用程序性能升,这对于高流量 Web API 和微服务尤其重要。

探索 ASP.NET Core Web API (Native AOT) 项目模板

.NET 8 引入了一个专门为原生 AOT 设计的全新项目模板 - "ASP.NET Core Web API (native AOT)" 项目模板。

此模板的简称为“webapiaot”,默认启用 AOT 发布。它是为希望从项目一开始就充分利用 AOT 编译潜力的开发人员量身定制的。此更新中的两个新功能是CreateSlimBuilder() 和CreateEmptyBuilder()方法。

CreateSlimBuilder 方法: 优化性能

CreateSlimBuilder 方法体现了微软致力于高性能开发的决心。它仅初始化 WebApplicationBuilder 中运行应用程序所需的基本 ASP.NET Core 功能。这个方法不仅简化了开发过程,而且确保应用程序保持轻量级和高性能。

CreateSlimBuilder 方法中包含的主要功能包括:

  • appsettings.json 和 appsettings.{EnvironmentName}.json 的 JSON 文件配置,实现强大而灵活的配置管理。
  • 集成用户机密配置,增强开发环境的安全性。
  • 内置控制台日志记录,方便直接调试和监控。
  • 全面的日志配置,为开发人员提供对应用程序行为的关键监控。
var builder = WebApplication.CreateSlimBuilder(args);

var app = builder.Build();

app.MapGet("/", () => "Hello World!");

app.Run();

但是,CreateSlimBuilder 这个极简方法省略了传统的 Startup.cs 文件,需要开发人员进行显式配置。它还删除了 EventLog、Debug 提供程序和 EventSource 主机 - 这些组件如果需要的话必须手动添加。还有一个比较重要的是,它没有开箱即用的 IIS、HTTPS、HTTP3 或完整的 Kestrel 服务器配置支持,需要开发人员有意添加这些功能来加强通信安全性和服务器健壮性。

这些可以通过显式添加到配置中来实现,例如看下面的示例如何实现这些自定义:

using Microsoft.AspNetCore.Routing.Constraints;

var builder = WebApplication.CreateSlimBuilder(args);

//http3 customization
builder.WebHost.UseQuic(); //Https customization
builder.WebHost.UseKestrelHttpsConfiguration(); //Regex customization
builder.Services.AddRouting().Configure<RouteOptions>(x =>
{
x.SetParameterPolicy<RegexInlineRouteConstraint>("Regex");
}); var app = builder.Build(); app.MapGet("/", () => "Hello World!"); app.Run();

CreateEmptyBuilder 方法: ** 最纯粹的定制**

.NET 8 的 CreateEmptyBuilder 方法体现了定制化的极致。它为开发者提供了一张白纸,让他们可以创造出定制化、小规模的应用程序。这反映了简单性和自主性的最高境界 - 只有开发者选择的组件才会被包含其中。

var builder = WebApplication.CreateEmptyBuilder(new WebApplicationOptions
{
Args =args
}); var app = builder.Build(); app.MapGet("/", () => "Hello World!"); app.Run();

为了确保应用程序正常运行,必须手动配置每个组件。如果在没有配置的情况下尝试执行上述代码,将发生错误。下面是一个正确的例子。

using Microsoft.AspNetCore.Routing.Constraints;

var builder = WebApplication.CreateEmptyBuilder(new WebApplicationOptions
{
Args = args
});
builder.WebHost.UseKestrelCore();
builder.Services.AddRoutingCore(); var app = builder.Build(); app.MapGet("/", () => "Hello World!"); app.Run();

性能测试结果: .NET 8 中的 Builder 方法

using BenchmarkDotNet.Attributes;
using Microsoft.AspNetCore.Routing.Constraints;
using System.Collections.Generic; namespace NewAppTypes
{
[MemoryDiagnoser]
public class BenchMarks
{
public string[]? Args { get; private set; } [Benchmark]
public void CreateBuilder()
{
var builder = WebApplication.CreateBuilder(Args);
var app = builder.Build();
builder.WebHost.UseUrls("http://*:80", "https://*.443"); app.MapGet("/", () => "Hello World!"); } [Benchmark]
public void CreateSlimBuilder()
{
var builder = WebApplication.CreateSlimBuilder(Args); //http3 customization
builder.WebHost.UseQuic(); //Https customization
builder.WebHost.UseKestrelHttpsConfiguration(); //Regex customization
builder.Services.AddRouting().Configure<RouteOptions>(x =>
{
x.SetParameterPolicy<RegexInlineRouteConstraint>("Regex");
}); var app = builder.Build();
builder.WebHost.UseUrls("http://*:80", "https://*.443");
app.MapGet("/", () => "Hello World!"); } [Benchmark]
public void CreateEmptyBuilder()
{
var builder = WebApplication.CreateEmptyBuilder(new WebApplicationOptions
{
Args = Args
});
builder.WebHost.UseKestrelCore();
builder.Services.AddRoutingCore(); var app = builder.Build();
builder.WebHost.UseUrls("http://*:80", "https://*.443");
app.MapGet("/", () => "Hello World!"); } }
}

性能测试结果揭示了一些有趣的性能数据。从结果中,我们可以观察到以下内容:

  • CreateBuilder 方法: 这是用于初始化 web 应用程序的标准方法,显示平均执行时间为 2682.3 微秒(us),分配内存约为 536.26 KB。这种方法设置了完整的 web 托管环境,具有所有默认服务和配置。执行时间和内存分配反映了这种全面性。

  • CreateSlimBuilder 方法: 优化后的 CreateSlimBuilder 方法记录了更快的平均执行时间为 1604.4 us,比 CreateBuilder 方法快约 40%。它还分配了更少的内存,约为 428.34 KB。这种性能提升可归因于减少了默认服务和配置的数量,这与该方法旨在提供更简化的启动过程的设计保持一致。

  • CreateEmptyBuilder 方法: 最简化的方法 CreateEmptyBuilder 展示了最快的平均执行时间为 121.3 us,明显快于其他两种方法。它还具有最低的内存占用,仅分配了 107.78 KB 左右。这突出了该方法的精简初始化策略,只包括显式定义的服务和配置。

标准差表明了多次运行中执行时间的可变性,其中 CreateBuilder 具有最高的可变性。这可能是由于要加载和配置的组件较多,这可能会导致初始化时间出现更多波动。

这些性能测试表明 CreateSlimBuilder,CreateEmptyBuilder 与传统 CreateBuilder 方法相比,它们具有显著的性能优势。当性能是关键因素时,开发人员应该考虑这些选项,特别是在启动时间和内存效率至关重要的环境中。

但需要注意的是,这些性能改进是以功能为代价的。虽然CreateEmptyBuilder提供了最快的启动速度和最低的资源消耗,但它要求开发人员手动配置所有必需的服务,这可能会增加开发的复杂性和时间。CreateSlimBuilder提供了一个折衷方案,提供了一些默认配置,同时仍允许更精简的应用程序设置。

结论

在 .NET 8 中,Builder 方法的选择不仅仅是一个技术决策,而是一个受项目独特需求影响的战略决策。性能测试为这一选择提供了量化基础,确保开发人员能够做出符合他们性能目标和开发理念的决策。

有关更多资料,请参阅 Microsoft Docs. (2023). “ASP.NET Core 8.0 release notes., https://learn.microsoft.com/en-us/aspnet/core/fundamentals/native-aot?view=aspnetcore-8.0,The 2 New Web Application Types Added in .NET 8

[翻译].NET 8 的原生AOT及高性能Web开发中的应用[附性能测试结果]的更多相关文章

  1. 高性能WEB开发(11) - flush让页面分块,逐步呈现

    高性能WEB开发(11) - flush让页面分块,逐步呈现 在处理比較耗时的请求的时候,我们总希望先让用户先看到部分内容,让用户知道系统正在进行处理,而不是无响应.一般大家在处理这样的情况,都使用a ...

  2. 高性能WEB开发:重排与重绘

    DOM编程可能最耗时的地方,重排和重绘. 1.什么是重排和重绘 浏览器下载完页面中的所有组件——HTML标记.JavaScript.CSS.图片之后会解析生成两个内部数据结构——DOM树和渲染树. D ...

  3. 高性能Web开发系列

    1. 高性能WEB开发基础 http://www.uml.org.cn/net/201404225.asp 2. 高性能WEB开发进阶(上) http://www.uml.org.cn/net/201 ...

  4. 高性能WEB开发:DOM编程

    我们知道,DOM是用于操作XML和HTML文档的应用程序接口,用脚本进行DOM操作的代价很昂贵.有个贴切的比喻,把DOM和Javascript(这里指ECMscript)各自想象为一个岛屿,它们之间用 ...

  5. 高性能WEB开发(6) - web性能測试工具推荐

    WEB性能測试工具主要分为三种.一种是測试页面资源载入速度的,一种是測试页面载入完成后页面呈现.JS操作速度的,另一种是整体上对页面进行评价分析,以下分别对这些工具进行介绍,假设谁有更好的工具也请一起 ...

  6. 高性能WEB开发 为什么要减少请求数,如何减少请求数!

    http请求头的数据量 [声明] 转载  原文出处:http://www.blogjava.net/BearRui/. 谢谢我们先分析下请求头,看看每次请求都带了那些额外的数据.下面是监控的googl ...

  7. 高性能web开发:如何加载js,,js的存放位置

    外部JS的阻塞下载 所有浏览器在下载JS的时候,会阻止一切其他活动,比如其他资源的下载,内容的呈现等等.至到JS下载.解析.执行完毕后才开始继续并行下载其他资源并呈现内容. 有人会问:为什么JS不能像 ...

  8. 高性能WEB开发:深入理解页面呈现、重绘、回流

    在讨论页面重绘.回流之前.需要对页面的呈现流程有些了解,页面是怎么把html结合css等显示到浏览器上的,下面的流程图显示了浏览器对页面的呈现的处理流程.可能不同的浏览器略微会有些不同.但基本上都是类 ...

  9. Android原生代码拦截H5 Web页面中JavaScript弹窗/弹框

    <html> <body> <script> function showAlert(){ alert("JavaScript - hello , worl ...

  10. 高性能WEB开发:Javascript自身执行效率

    Javascript中的作用域链.闭包.原型继承.eval等特性,在提供各种神奇功能的同时也带来了各种效率问题,用之不慎就会导致执行效率低下. 1.全局导入 我们在编码过程中多多少少会使用到一些全局变 ...

随机推荐

  1. WPF 在 .NET Core 3.1.19 版本 触摸笔迹偏移问题

    在更新到 .NET 6 发布之前的,在 2021.11.02 的 .NET Core 版本,都会存在此问题.在 WPF 应用里面,如果在高 DPI 下,进行触摸书写,此时的笔迹将会偏移.核心原因是在这 ...

  2. WPF 如何获取有哪些 VisualBrush 用了某个控件

    我写了一个特殊的控件,我期望了解到有哪些 VisualBrush 捕获了此控件,或者说有哪些 VisualBrush 用了此控件的界面 本文的方法需要用到反射,需要使用 WPF 框架里面没有公开的字段 ...

  3. 微信小程序支付实现流程

    基本流程 用户操作流程 小程序流程 整体支付流程 代码实现 创建订单 创建订单,主要是前端将订单的信息提交到后端.但是在创建订单之前还有一些准备工作要做: 获取用户数据GetUserInfo 获取用户 ...

  4. kubernetes-1.26安装

    一.环境准备 k8s集群角色 IP 主机名 安装组件 配置 控制节点 192.168.10.10 master apiserver.controller-manager.scheduler.etcd. ...

  5. Gradle构建SpringBoot单模块项目

    Gradle构建SpringBoot单模块项目 方式Ⅰ:未基于:Gradle Wrapper 方式Ⅱ:(推荐使用)Gradle Wrapper[可以不安装Gradle.统一Gradle的版本]--包括 ...

  6. .Net 8.0 下的新RPC,IceRPC之试试的新玩法"打洞"

    作者引言 很高兴啊,我们来到了IceRPC之试试的新玩法"打洞",让防火墙哭去吧 试试RPCs的新玩法"打洞" 比较典型的玩法:RPC数据流从客户端流向服务端, ...

  7. ruby后台传变量到前端的JS里

    后端变量 @namelist 前端解释 var result_json = <%= @namelist.to_json.html_safe %>

  8. gin里获取http请求过来的参数

    https://www.bilibili.com/video/av68769981/?p=2 课程代码: https://www.qfgolang.com/?special=ginkuangjia&a ...

  9. Python字符串方法:字符串查找、替换、分割

    字符串查找 Python 提供了内置的字符串查找方法find(),利用该方法可以在一个较长的字符串中查找子字符串.如果该字符串中,有一个或者多个子字符串,则该方法返回第一个子串所在位置的最左端索引,若 ...

  10. 一款基于C#开发的通讯调试工具(支持Modbus RTU、MQTT调试)

    前言 今天大姚给大家分享一款基于C#.WPF.Prism.MaterialDesign.HandyControl开发的通讯调试工具(支持Modbus RTU.MQTT调试,界面色彩丰富):Wu.Com ...