.NET 8 极致性能优化 AOT
前言
.NET8对于性能的优化是方方面面的,所以AOT预编译机器码也是不例外的。本篇来看下对于AOT的优化。
概述
首先要明确一个概念,.NET里面的AOT它是原生的。什么意思呢?也就是说通过ILC编译器(AOT编译器,参考:.Net 7 新编译器 ILC 简析)编译出来的代码是各个平台上可以直接运行的二进制代码。比如MacOS的二进制,Linux二进制等等。所以称之为原生。
C#源码被ILC编译之后,生成了一个完全原生态代码的可执行文件。在执行的时候不需要JIT来编译任何东西,因为JIT已经在ILC里面被充分利用过了。实际上AOT里面也没有包含JIT。那么它如何优化呢?只能是在ILC里面调用JIT的时候了。所以它这个优化依然依靠JIT。.NET8里面优化AOT的一个典型的例子,就是ASP.NET应用程序在使用AOT的时候表现不错,同时也降低了总成本。
在.NET8里面优化AOT的一个重要的目标就是减少AOT可执行文件的大小,关于这点的效果。我们现在就可以看到
下面创建一个控制台应用程序
dotnet new console -o nativeaotexample -f net7.0
由于上面是通过.NET7.0创建的,我们把这个控制台的csproj更改下
<TargetFramework>net7.0</TargetFramework>
改为
<TargetFrameworks>net7.0;net8.0</TargetFrameworks>
可以轻松的构建.NET7.0或者.NET8.0的程序
继续
把<PropertyGroup>...</PropertyGroup>项中添加如下
<PublishAot>true</PublishAot>编译成AOT文件
下面我们就可以通过dotnet publish发布它了,linux如下:
dotnet publish -f net7.0 -r linux-x64 -c Release
现在它生成了一个.NET7.0版本的独立可执行文件,可通过 ls/dir 输出目录以查看生成的二进制大小
12820K /home/stoub/nativeaotexample/bin/Release/net7.0/linux-x64/publish/nativeaotexample
这个大约是13M左右,我们再来看下.NET8.0
dotnet publish -f net8.0 -r linux-x64 -c Release
生成的可执行文件大小如下:
1536K /home/stoub/nativeaotexample/bin/Release/net8.0/linux-x64/publish/nativeaotexample
1.5M的大小,这个优化的力度不可不大啊。整整优化了将近10倍的体积。这就是.NET8.0的优化魔力。
但是优化的情况远不止如此,比如说我们可以配置csproj使AOT的体积更小
csproj添加如下size表示要生成的AOT大小
<OptimizationPreference>Size</OptimizationPreference>
如果我们不需要全球化代码和数据,需要特定的代码和数据,并且使用不变模式,可以csproj添加如下选项
<InvariantGlobalization>true</InvariantGlobalization>
如果你不想在AOT异常的时候抛出堆栈,那么你也可以在csproj里面添加如下
<StackTraceSupport>false</StackTraceSupport>
重新通过dotnet publish net8.0发布了之后,它的体积还可以继续减小
1248K /home/stoub/nativeaotexample/bin/Release/net8.0/linux-x64/publish/nativeaotexample
再次缩小了0.3M大小。
然而,你以为到此优化就为止了吗?并没有,.NET8不仅对AOT编译器内部进行了改进,而且还对单个库也进行了性能优化和改进。比如HttpClient。
当然除了体积的优化之外,还有其它的优化,比如避免了在读取静态字段时的辅助调用,再比如BenchmarkDotNet 也是支持AOT化的,也就是性能测试上面的支持。我们可以只使用 --runtimes nativeaot7.0 nativeaot8.0,而不使用 --runtimes net7.0 net8.0,如下代码
// dotnet run -c Release -f net7.0 --filter "*" --runtimes nativeaot7.0 nativeaot8.0
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
BenchmarkSwitcher.FromAssembly(typeof(Tests).Assembly).Run(args);
[HideColumns("Error", "StdDev", "Median", "RatioSD")]
public class Tests
{
private static readonly int s_configValue = 42;
[Benchmark]
public int GetConfigValue() => s_configValue;
}
上面代码可以通过如下AOT化运行
dotnet run -c Release -f net7.0 --filter "*" --runtimes nativeaot7.0 nativeaot8.0
BenchmarkDotNet 输出如下
Method | Runtime | Mean | Ratio |
---|---|---|---|
GetConfigValue | NativeAOT 7.0 | 1.1759 ns | 1.000 |
GetConfigValue | NativeAOT 8.0 | 0.0000 ns | 0.000 |
可以看到即使是性能测试的Benchmark,AOT优化也是不放过的。
另外还值得一提的地方就是分层,因为AOT里面没有分层的概念。但是即时编译也就是不是AOT编译的时候,一个方法从tier0提升到tier1,方法里面的静态字段必须被初始化过了。AOT里面添加了一个快速路径检查字段是否初始化,避免一些不必要的开销。
其它的一些改进,比如AOT锁的实现方式。使用了一种混合方式,开始使用轻量级自旋锁,后面升级到使用 System.Threading.Lock 类型,这个应该会在.NET9.0里面释放出来。
欢迎关注公众号(jianghupt),文章首发地。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
谷歌推迟“最强 AI”Gemini 的发布
The Information 援引知情人士消息称,谷歌已悄悄地将旨在与 OpenAI 竞争的对话式人工智能 Gemini 的公开亮相推迟到 2024 年 1 月。 谷歌在 2023 年 I/O 大会上首次透露正在开发 Gemini 以作为下一代基础模型,据称这是该公司迄今为止创建的最强大的对话式 AI。Gemini 被描述为一个可以处理多种数据的多模态 AI 聊天机器人,能够根据草图和书面描述的结合来理解和生成文本、图像和其他类型的内容。还可以根据用户的要求总结文本、帮助软件工程师编写代码等。 该公司表示,新模型将展现出“令人印象深刻的多模态能力”,这是之前的任何大模型中都从未出现过的。此外,他们还在开发 API,使得开发人员可以直接将 Gemini 集成到第三方应用程序中。 谷歌原定于本周在美国纽约、华盛顿和加州举行的发布会上推出 Gemini,但在他们“发现 AI 无法可靠地处理一些非英语查询”后。首席执行官 Sundar Pichai 决定取消原定的一系列活动,并推迟 Gemini 的发布。谷歌希望 Gemini 最终能超越 OpenAI 的 GPT-4 模型,而全球化支持是 ...
- 下一篇
让代码运行起来,比代码可读性重要
"代码的阅读胜于编写"这句话现在已经是程序员共识,它提醒我们,在编写代码时不能仅追求方便,而忽视那些将来需要阅读和修改代码的人。更一般地说,"代码的阅读胜于编写"传达了一个观点:通过保持代码可维护性,保持简洁、编写测试和文档等方式来使得代码易于理解是一个明智的投资。它关乎对软件开发周期的全局视角。 让我用更简洁的表达方式来表述这个观点: 维护者 > 作者 我认为这种思路可以超越编写代码,并作为一个经验法则用于问题识别和决策。 代码的使用胜于阅读 代码只是达到目标的手段。软件应该有一个目的,它应该为用户提供服务。无论代码是否编写良好、可维护性如何,以及所使用技术是否先进,如果软件不能实现其目标并给用户带来良好体验,则一切都没有意义: 用户 > 维护者 > 作者 或者,既然我们不再需要区分开发人员角色: 用户 > 开发者 因此,与其猜测或询问用户需求,最好的方法是尽早、频繁地将程序放在用户面前,并结合他们的反馈来改进。 这是一个强大的思维模式,只要在开发过程中牢记用户,我们就能走得更远。这大致是我学习这个职业以及我职业生涯前半段对它的理解方式。 代码的运行胜于阅读 ...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- Docker安装Oracle12C,快速搭建Oracle学习环境
- CentOS7安装Docker,走上虚拟化容器引擎之路
- Linux系统CentOS6、CentOS7手动修改IP地址
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- CentOS关闭SELinux安全模块
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- Hadoop3单机部署,实现最简伪集群
- CentOS6,7,8上安装Nginx,支持https2.0的开启