浅尝.NET7 NativeAOT

时间:07/04/2023 19:34:12   作者:ChenReal    阅读:141

一、前言

NativeAOT是.NET7的新特性,可以将.NET代码编译成操作系统原生的应用程序或者类库运行,不依赖.NET运行环境。自从它面世以来在.NET圈子内一直颇受关注,跃跃欲试的人当中自然也包括了区区在下。观望了一年多,今天我终于出手,浅尝了一下传说中的.NET NativeAOT。

二、开发环境

开头必是搭建开发环境,准确来说应该是编译环境才算比较准确。因为NativeAOT有个臭脾气——不能跨平台编译。编译windows应用必须在windows环境下;编译linux应用必须在linux环境下;编译osx应用必须在mac环境下。否则,立马会给你脸色看:Cross-OS native compilation is not supported.

但,这难不倒在下,以上的操作系统俺都有!

1、MacOS

Mac是我的主力开发系统,Visual Studio For Mac早就是最新的Stable版本。因此,上手非常顺利。随便创建一个输出“Hello World”的.NET7控制台项目,然后,修改*.csproj文件,加上<PublishAot>true</PublishAot>就完事了。编译也相当顺利,跑完一下脚本命令。

dotnet publish DemoAot.csproj -o $PWD/pub -c Release -r osx-x64

10秒钟后,一个大小8M的AOT应用程序就出炉了。测运行了一下,还真能跑出“Hello World”。

2、Linux

我的编译环境是Debian11的虚拟机,安装好.NET7 SDK后。同样跑了一下上面的脚本:

dotnet publish DemoAot.csproj -o $PWD/pub -c Release -r linux-x64

出现了报错,提示缺少了clang编译库。那么按照官方指示安装上

apt-get install clang zlib1g-dev

再跑发布脚本,出来了一个10M左右的执行文件。按照网上的办法给工程文件(*.csproj),加上`true可以裁剪发布文件的大小,对Linux比较有效。果然加上之后文件大小变成了3.77M。

3、Windows

windows环境下的编译发布,似乎比上述两个都要麻烦一些。首先,即使已经安装了Visual Studio 2022还不够,还要安装C++做面开发环境(对于大多数只写C#的开发者,一般这都不会装这个的)。

aot-1.png

为了体验NativeAOT,我也只能重新打开VS的installer跑了4-5个小时,终于把这东西下载安装好了。然后,马不停蹄跑了一下发布脚本。很快,一个for windows的exe执行文件就被生成出来了,大小只有2.5M左右。比前面两个系统发布的文件都要小一些。

dotnet publish DemoAot.csproj -o pub\ -c Release -r win-x64

三、应用实战

上面用“Hello World”应用跑通了NativeAOT的编译环境,那么接下来,就要挑战一下复杂一些的应用,看看NativeAOT是否能够经得住实战的考验,可以成为技术开发的首选方案。

1、控制台应用

我们还是从控制台应用开始,当然接下来的肯定不是简单的输出“Hello World”这样的应用了,而是有使用功能的。 aot-2.png

比如,这个StockMonitor,是很久之前用.NET Core3.1开发的一个小应用。主要功能是HttpClient抓取每日股票数据,整理发送到LeanCloud的对象存储服务中,然后从LeanCloud读取一段时间的数据进行分析,给出买入卖出建议。项目主要用到的库有这个几个:

  • LeanCloud SDK(Common、Storage、Standard)
  • Newtonsoft.Json
  • System.Net
  • System.Text.Encoding.CodePages

照例,我们把工程文件改造一番:

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net7.0</TargetFramework>
    <LangVersion>latest</LangVersion>
    <SatelliteResourceLanguages>en</SatelliteResourceLanguages>
    <RuntimeIdentifiers>linux-x64</RuntimeIdentifiers>
    <_IsPortable>true</_IsPortable>
    <PublishAot>true</PublishAot>
    <StripSymbols>true</StripSymbols>
  </PropertyGroup>

然后脚本编译发布

dotnet publish StockMonitor.csproj -o $PWD/pub -c Release -r osx-x64

居然非常的顺利,应用发布成功了!没有改任何代码。那么,试一下能否执行吧。

./StockMonitor fetch sh000001

./StockMonitor fetch sh000001 Start StockMonitor... Run fetch-sh000001... 上 证 指 数 时 间 : 7/4/2023 12:05:00 PM

昨 收 : 3243.98 今 开 : 3241.23 当 前 : 3246.13 涨 幅 : 0.07%

太好了,也成功了!不过执行文件的Size涨到了67M,先不管它,肯定还是有办法做裁剪的。听说换成.NET8就可以将NativeAOT编译文件减半。

2、WebAPI

一系列的成功,让我对NativeAOT的信心瞬间膨胀了起来。下面开始挑战WebAPI应用,整个ASP.NET的Web框架都引入过来,会有奇迹发生吗? aot-3.png

  • 创建一个简单的WebAPI项目,使用最简单的MiniAPI,做了一个API方法“weatherforecast”。
var builder = WebApplication.CreateBuilder(args);

var app = builder.Build();

app.UseHttpsRedirection();

var summaries = new[]
{
    "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

app.MapGet("/weatherforecast", () =>
{
var forecast = Enumerable.Range(1, 5).Select(index =>
   new WeatherForecast
   (
       DateTime.Now.AddDays(index),
       Random.Shared.Next(-20, 55),
       summaries[Random.Shared.Next(summaries.Length)]
   ))
    .ToArray();
return forecast;
})
.WithName("GetWeatherForecast");

app.Run();

internal record WeatherForecast(DateTime Date, int TemperatureC, string? Summary)
{
    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
  • 编译发布,也是成功的,exe执行文件大小25M。
  • 双击打开运行,表面看起来是跑起来了。但是,打开浏览器访问API接口,报错便随之而来了。看起来是System.Text.Json序列化出了问题,试验宣告失败!aot-10.png
  • 当然,还有改进的可能,譬如将Json库换成Newtonsoft.Json说不定能够迈过这个坑呢?等下次有机会再试一试吧。

四、总结

  • NativeAOT是初衷非常好的,让C#语言可适用的疆界做了一次扩展以及重定义,虽然目前看来还有很多不成熟的地方。相信在将来.NET8、.NET9可能得到很好的解决,最终可以跟C++、Go、Rust这些原生应用领域的编译语言一较高下。
  • 鉴于目前的NativeAOT使用的限制还是比较多的,因此能够开发的应用类型还是比较少的,因此开发一些小工具小应用能够胜任,但是并不建议企业商用项目使用,否者将会是个无底深坑。
  • 让NativeAOT再飞一会吧!

参考资料

https://learn.microsoft.com/zh-cn/dotnet/core/deploying/native-aot/?tabs=net7

https://www.netnr.com/home/list/185

 

评论
0/200