[翻译].NET 8 的原生AOT及高性能Web开发中的应用[附性能测试结果]
原文: [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开发中的应用[附性能测试结果]的更多相关文章
- 高性能WEB开发(11) - flush让页面分块,逐步呈现
高性能WEB开发(11) - flush让页面分块,逐步呈现 在处理比較耗时的请求的时候,我们总希望先让用户先看到部分内容,让用户知道系统正在进行处理,而不是无响应.一般大家在处理这样的情况,都使用a ...
- 高性能WEB开发:重排与重绘
DOM编程可能最耗时的地方,重排和重绘. 1.什么是重排和重绘 浏览器下载完页面中的所有组件——HTML标记.JavaScript.CSS.图片之后会解析生成两个内部数据结构——DOM树和渲染树. D ...
- 高性能Web开发系列
1. 高性能WEB开发基础 http://www.uml.org.cn/net/201404225.asp 2. 高性能WEB开发进阶(上) http://www.uml.org.cn/net/201 ...
- 高性能WEB开发:DOM编程
我们知道,DOM是用于操作XML和HTML文档的应用程序接口,用脚本进行DOM操作的代价很昂贵.有个贴切的比喻,把DOM和Javascript(这里指ECMscript)各自想象为一个岛屿,它们之间用 ...
- 高性能WEB开发(6) - web性能測试工具推荐
WEB性能測试工具主要分为三种.一种是測试页面资源载入速度的,一种是測试页面载入完成后页面呈现.JS操作速度的,另一种是整体上对页面进行评价分析,以下分别对这些工具进行介绍,假设谁有更好的工具也请一起 ...
- 高性能WEB开发 为什么要减少请求数,如何减少请求数!
http请求头的数据量 [声明] 转载 原文出处:http://www.blogjava.net/BearRui/. 谢谢我们先分析下请求头,看看每次请求都带了那些额外的数据.下面是监控的googl ...
- 高性能web开发:如何加载js,,js的存放位置
外部JS的阻塞下载 所有浏览器在下载JS的时候,会阻止一切其他活动,比如其他资源的下载,内容的呈现等等.至到JS下载.解析.执行完毕后才开始继续并行下载其他资源并呈现内容. 有人会问:为什么JS不能像 ...
- 高性能WEB开发:深入理解页面呈现、重绘、回流
在讨论页面重绘.回流之前.需要对页面的呈现流程有些了解,页面是怎么把html结合css等显示到浏览器上的,下面的流程图显示了浏览器对页面的呈现的处理流程.可能不同的浏览器略微会有些不同.但基本上都是类 ...
- Android原生代码拦截H5 Web页面中JavaScript弹窗/弹框
<html> <body> <script> function showAlert(){ alert("JavaScript - hello , worl ...
- 高性能WEB开发:Javascript自身执行效率
Javascript中的作用域链.闭包.原型继承.eval等特性,在提供各种神奇功能的同时也带来了各种效率问题,用之不慎就会导致执行效率低下. 1.全局导入 我们在编码过程中多多少少会使用到一些全局变 ...
随机推荐
- C++里也有菱形运算符?
最近在翻<c++函数式编程>的时候看到有一小节在说c++14新增了"菱形运算符".我寻思c++里好像没什么运算符叫这名字啊,而且c++14新增的功能很少,我也不记得有添 ...
- WordPress 整合Bootstrap制作分页代码
1.整合Bootstrap分页代码 * 因为wordpress默认仅仅提供简单分页, 所以要实现数字分页,需要自定义函数,wordpress可以结合bootstrap制作分页,bootstrap提供了 ...
- gRPC入门学习之旅(八)
gRPC入门学习之旅(一) gRPC入门学习之旅(二) gRPC入门学习之旅(三) gRPC入门学习之旅(四) gRPC入门学习之旅(五) gRPC入门学习之旅(六) gRPC入门学习之旅(七) 3. ...
- Splashtop远程桌面再次增强:支持4K视频流
远程桌面工具,主流的有10款总有,国内用的比较多的有teamviewer.Splashtop.向日葵等.几款软件各有千秋,其中Splashtop最大的特性就是快速.流畅.产品无敌,运营佛系,哈哈.下面 ...
- 关于UE4对象静态/动态的销毁问题整理(AddToRoot、TWeakObjectPtr)
1.非UObject对象 即非UObject常规C++对象,创建销毁不赘述.但可以用智能指针:从而不用关心销毁逻辑: TSharedPtr<ClassA> MyObj = MakeShar ...
- rbenv:Ruby 多版本管理利器
在 Ruby 开发的世界中,经常需要面对不同项目使用不同 Ruby 版本的情况.这时,一个高效.灵活且易于使用的 Ruby 版本管理工具就显得尤为重要. rbenv 正是这样一个工具,它允许开发者在同 ...
- 数据结构(C++)--学习单链表时发现的一些小坑
基于类的链表类无相应构造函数报错 #include<bits/stdc++.h> using namespace std; const int MaxSize = 10; template ...
- 算法金 | 详解过拟合和欠拟合!性感妩媚 VS 大杀四方
大侠幸会,在下全网同名「算法金」 0 基础转 AI 上岸,多个算法赛 Top 「日更万日,让更多人享受智能乐趣」 今天我们来战 过拟合和欠拟合,特别是令江湖侠客闻风丧胆的 过拟合,简称过儿, Emmm ...
- iOS符号表手工还原
1.通过Xcode的Device工具导出app.crash文件 2.将.crash 和 .dSYM符号 app放在同一个目录中 3.寻找symbolicatecrash,将symbolicatecra ...
- python+k8s——基础练习
列表 core_api = client.CoreV1Api() # 管理核心资源(Pod, Service, ConfigMap 等) apps_api = client.AppsV1Api() # ...