.Net native aot简单体验(一)

发布时间 2023-09-02 15:27:30作者: 天方

.net native aot可以在发布时将 IL 代码编译为本地代码,从而提高应用程序的性能和效的发布方式,其主要优点有:

  • 缩小磁盘占用
  • 降低启动时间
  • 减少内存需求

如果用于个人发布的小程序来说,还有如下两个优点:

  • 不用安装
  • 防止反编译

虽然.net 7就已经支持native aot了,但只能用于控制台程序,使用场景有很大的限制,并没有怎么研究它。最近装了.net 8 preview版,发现是支持asp.net的aot的,便找了个时间简单的体验下aot。

前置条件

由于NativeAOT需要c++编译器将其变成native程序,因此除了.net core sdk外,还需要安装C++编译器, 在Windows下微软提供的方案是安装 "Desktop development with C++"的工作负载。

这还还需要附带安装一个VisualStudio,算是一个比较重的安装了。根据微软的文章,目前没有提供不安装VisualStudio的方案的计划。

参考文章:Tutorial: Publish an ASP.NET Core app using native AOT。

 

简单示例

以一个简单的控制台程序为例:

Console.WriteLine("Hello, World!");

要添加aot发布选项,有两个方法:

1. 在csproj项目文件中添加PublishAot选项
<PropertyGroup>
    <PublishAot>true</PublishAot>
</PropertyGroup>

这样,通过dotnet publish发布的时候,会自动将其发布成native aot的程序

但需要注意的是,放在csproj的时候,会对ide造成一定的影响,会导致在ide中进行aot,这并不是我们所需要的,此时需要加条件参数 Condition=" '$(Configuration)' == 'Release' "

2. 在命令行中添加参数/p:PublishAot=true,完整命令如下:

dotnet publish /p:PublishAot=true

这两种方式本质是一样的,实际上,在PropertyGroup中的所有参数都可以通过/p的方式动态添加。在命令行中更灵活,具体看怎么使用看需求了。

打包后,由于这个程序非常简单,直接成功了,我使用的是.net 8 preview的版本,最终的发布包只有1.4m。看来.net 8对native aot有了进一步的优化。

 

WinForm程序AOT

目前.net 8还不支持对winform的aot,aot的时候会出现如下错误:Error NETSDK1175 : 启用剪裁时,不支持或不推荐使用 Windows 窗体

不过这个错误可以通过_SuppressWinFormsTrimError参数屏蔽掉

<PropertyGroup>
    <PublishAot>true</PublishAot>
    <_SuppressWinFormsTrimError>true</_SuppressWinFormsTrimError>
</PropertyGroup>

屏蔽掉后,可以顺利生产Native的程序,也能正常的启动和执行。不过编译过程中伴随着一大堆的告警,如果用这种方式发布文件还是需要好好测试的。

和控制台程序比起来,由于WinForm包含了UI库,其输出程序要大得多,达到了54mb。虽然对比100mb+的自包含模式要校不少,但如果是小程序这个体积还是有点难以接受的。由于已经是native程序了,我便尝试了用upx压缩了一下:

./upx --best WinFormsApp1.exe

File size Ratio Format Name
-------------------- ------ ----------- -----------
57275904 -> 17455616 30.48% win64/pe WinFormsApp1.exe

压缩效果还是非常令人满意的,带ui的winform程序直接被压缩到了16m,体积基本上解决7z的压缩包了。 后续的小程序都可以直接用这种方式发布了,不用安装运行时直接启动还是非常有吸引力的。

 

WPF程序AOT

WPF程序和WinForm一样不支持aot,会报错不支持,虽然有参数_SuppressWPFTrimError可以使用,但是编译后的程序无法启动。由于WPF程序使用了大量反射,支持aot天生有难度,估计短期是不用指望了。