前言

.NET8对于性能的优化是方方面面的,所以AOT预编译机器码也是不例外的。本篇来看下对于AOT的优化。原文:.NET8极致性能优化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

原文:.NET8极致性能优化AOT

文章公众号(jianghupt)首发,欢迎关注

.NET8极致性能优化AOT的更多相关文章

  1. MIS性能优化常见问题与方案(辅助项目组性能优化的总结贴)

    最近帮忙公司的几个项目组进行了不同方面的性能优化,发现几个项目都出现了一些共性的问题.这里写一篇文章,总结一下这几类问题,以及其对应的解决方案.方便其它项目组参考.   常见问题一:打开页面非常慢,有 ...

  2. 【前端构建】WebPack实例与前端性能优化

    计划把微信的文章也搬一份上来. 这篇主要介绍一下我在玩Webpack过程中的心得.通过实例介绍WebPack的安装,插件使用及加载策略.感受构建工具给前端优化工作带来的便利. 壹 | Fisrt 曾几 ...

  3. Android应用性能优化(转)

    人类大脑与眼睛对一个画面的连贯性感知其实是有一个界限的,譬如我们看电影会觉得画面很自然连贯(帧率为24fps),用手机当然也需要感知屏幕操作的连贯性(尤其是动画过度),所以Android索性就把达到这 ...

  4. Web前端性能优化教程09:图像和Cookie优化

    本文是Web前端性能优化系列文章中的第九篇,主要讲述内容:图像和Cookie优化.完整教程可查看:  一. 图像优化 图像基础知识 gif: 适用于动画效果,例如提示的滚动条图案 jpg: 是一种使用 ...

  5. Web前端性能优化教程07:精简JS 移除重复脚本

    本文是Web前端性能优化系列文章中的第七篇,主要讲述内容:精简Javascript代码,以及移出重复脚本.完整教程可查看:  一.精简javascript 基础知识 精简:从javascript代码中 ...

  6. web前端性能优化

    性能优化对于用户体验无疑是非常重要的,下面介绍一些性能优化的方法. 1.减少HTTP请求 http请求越多,那么消耗的时间越多,如果在加上网络很糟糕,那么问题就更多了.且如果网页中的图片.css文件. ...

  7. 一些新的web性能优化技术

    1.IconFont:图标字体,这是近年来新流行的一种以字体代替图片的技术.它可以适应任何分辨率而不会出现图片模糊问题,与图片相比它具有更小的容量,更高的灵活性(像字体一样可以设置图标大小.颜色.透明 ...

  8. Web 前端性能优化准则

    准则01:尽量减少http请求 “只有10%-20%的最终用户响应时间花在接收请求的HTML文档上,剩下的80%-90%时间花在HTML文档所引用的所有组件(图片,script,css,flash等等 ...

  9. 【原/转】UITableview性能优化总结

    UITableView作为ios中使用最频繁的控件之一,其性能优化也是常常要面对的,尤其是当数据量偏大并且设备性能不足时.本文旨在总结tableview的几个性能优化tips,并且随着认识的深入,本文 ...

  10. mysql数据库性能优化(包括SQL,表结构,索引,缓存)

    优化目标减少 IO 次数IO永远是数据库最容易瓶颈的地方,这是由数据库的职责所决定的,大部分数据库操作中超过90%的时间都是 IO 操作所占用的,减少 IO 次数是 SQL 优化中需要第一优先考虑,当 ...

随机推荐

  1. nlp入门(三)基于贝叶斯算法的拼写错误检测器

    源码请到:自然语言处理练习: 学习自然语言处理时候写的一些代码 (gitee.com) 数据来源:norvig.com/big.txt 贝叶斯原理可看这里:机器学习算法学习笔记 - 过客匆匆,沉沉浮浮 ...

  2. 浅谈Mysql读写分离的坑以及应对的方案

    一.主从架构 为什么我们要进行读写分离?个人觉得还是业务发展到一定的规模,驱动技术架构的改革,读写分离可以减轻单台服务器的压力,将读请求和写请求分流到不同的服务器,分摊单台服务的负载,提高可用性,提高 ...

  3. 《Python魔法大冒险》009 魔法之语:字符串的奥秘

    随着小鱼和魔法师的深入,他们来到了一个被薄雾笼罩的湖泊.湖中央有一个小岛,岛上有一棵巨大的古树,树上挂满了闪闪发光的果实,每一个果实上都刻着一个字母或符号. 小鱼好奇地问:"这些是什么果实? ...

  4. C与CPP常见编译工具链与构建系统简介

    笔者最近在研究CEF的CMake工程,心血来潮想要对各种编译工具链以及构建系统做一个简单的总结,于是就有了本文.本文不会讲解任何关于C/C++语言方面的内容,主要C/C++的编译出发,介绍各种编译工具 ...

  5. Vue源码学习(五):<templete>渲染第四步,生成虚拟dom并将其转换为真实dom

    好家伙,   前情提要: 在上一篇我们已经成功将ast语法树转换为渲染函数  现在我们继续   1.项目目录 代码已开源https://github.com/Fattiger4399/analytic ...

  6. Towards Network Anomaly Detection Using Graph Embedding笔记

    Towards Network Anomaly Detection Using Graph Embedding 目录 Towards Network Anomaly Detection Using G ...

  7. Python基础——计算机组成原理、操作系统概述、编程语言的由来、编程语言分类、python介绍、 安装Cpython解释器、 第一个python程序

    文章目录 一 引子: 1.1 什么是语言?什么是编程语言?为何要有编程语言? 1.2 什么是编程?为什么要编程? 二 计算机组成原理 2.1.什么是计算机? 2.2.为什么要用计算机? 2.3.计算机 ...

  8. tmai

    天猫精灵技能应用平台合作协议 发布日期:2020年03月18日 更新日期:2021年02月01日 鉴于您(语音技能.小程序或应用程序APP等的制作.提供或开发者)希望入驻或与天猫精灵技能应用平台(又称 ...

  9. 造轮子之ORM集成

    Dotnet的ORM千千万,还是喜欢用EF CORE 前面一些基础完成的差不多了,接下来可以集成数据库了,官方出品的ORM还是比较香.所以接下来就是来集成EF CORE. 安装包 首先我们需要安装一下 ...

  10. C静态库的创建与使用--为什么要引入静态库?

    C源程序需要经过预处理.编译.汇编几个阶段,得到各自源文件对应的可重定位目标文件,可重定位目标文件就是各个源文件的二进制机器代码,一般是.o格式.比如:util1.c.util2.c及main.c三个 ...