首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

.NET 的 Native AOT 现在是什么样的?

编程知识
2024年09月15日 09:10


在软件开发领域,优化性能和简化效率仍然至关重要。多年来,.NET 平台一直在创新,为开发人员提供基础设施,以打造弹性和高效的软件解决方案。今天要写的这篇文章源自昨天在朋友圈发的文章《UWP 通过 .NET 9 和Native AOT 的支持实现 UWP 应用的现代化》[1],一位小伙伴的对话让我想全面梳理下Native AOT的现在的进展。

image

什么是 .NET Native AOT?

.NET Native Ahead-of-Time (AOT) 编译是 .NET 平台中的一项前沿进步。使用 AOT 时,C# 代码在开发人员计算机上被编译为本机代码。这与在运行时将代码编译为本机代码的传统方法形成鲜明对比。

下面的架构说明了这一点。.NET 传统编译涉及两个步骤:

  1. C# 编译生成包含中间语言 (IL) 代码的 DLL 文件。此类 DLL 称为 .NET 程序集
  2. 执行 .NET 程序时,.NET 运行时CLR 公共语言运行时)将加载 .NET 程序集。CLR 的子系统负责将 IL 代码编译为由 CPU 直接执行的本机代码。此子系统称为 JIT (Just-In-Time) 编译器。它之所以得名,是因为它仅在首次调用该方法时编译该方法的 IL 代码。

另一方面,.NET Native AOT 编译由一个步骤组成。将 C# 源代码编译为开发人员计算机上的本机代码。此过程包括将 C# 代码转换为 IL 代码,然后转换为 Native 代码,形成一个两步编译过程。但这是一个实现细节。这就是 AOT .NET 程序集 框在下面的架构中为灰色的原因。

image

.NET Native AOT 的优势

.NET Native Ahead-of-Time (AOT) 编译带来了一系列优势:

  • 增强的性能:通过将代码预编译为本机计算机指令,.NET Native AOT 显著缩短了启动时间并提高了应用程序的整体性能。在无服务器方案中,如果应用程序针对每个请求启动,这可能会产生重大差异。此外,运行时没有 JIT 编译开销,这意味着执行速度更快,从而提供更流畅的用户体验。
  • 简化部署:AOT 编译的应用程序通常会导致依赖项为零或较少的独立可执行文件。这简化了部署过程,可以更轻松地在各种平台和设备之间分发应用程序,而无需额外的安装或运行时组件。
  • 更小的应用程序大小:通过修剪不必要的代码,AOT 可以大大减小应用程序的大小。这不仅可以节省存储空间,还可以优化应用程序的内存占用,这在移动设备或 IoT 设备等资源受限的环境中尤为重要。
  • 增强的知识产权保护:AOT 编译将源代码转换为优化的机器代码,这使得逆向工程尝试更具挑战性。生成的本机代码比 IL 代码更加模糊,并且难以破译,因为 IL 代码可以轻松反编译为原始 C# 代码。这增强了应用程序中嵌入的敏感算法、业务逻辑和专有方法的安全性。

.NET Native AOT 的缺点

使用 AOT 获得的好处不可避免地伴随着某些缺点。他们是:

  • 特定于平台的编译:.NET Native AOT 生成特定于平台的本机代码,针对特定体系结构或操作系统进行定制。例如,与常规 .NET 程序集不同,在 Windows 上使用 AOT 生成的可执行文件在 Linux 上不起作用。
  • 不支持跨 OS 编译。例如,在 Windows 机器上,您无法编译 Linux 本机版本,反之亦然。
  • 对 Reflection 的部分支持:反射依赖于动态代码生成和运行时类型发现,这与 AOT 编译代码的预编译和静态性质相冲突。但是,通常的 Reflection 用法与 AOT 配合得很好。
  • 需要 AOT 兼容的依赖项:AOT 编译要求项目中使用的所有库和依赖项都与 AOT 兼容。依赖于反射、运行时代码生成或其他动态行为的库可能与 AOT 不兼容,这可能会导致冲突或运行时错误。
  • 增加构建时间:AOT 编译涉及在构建过程中预先生成本机代码。这个额外的步骤会显著增加构建时间,特别是对于大型项目或具有大量代码库的应用程序。
  • 需要适用于 C++ 的桌面开发工具:AOT 只能在安装这些工具的情况下进行编译,这些工具在您的硬盘驱动器上最多可重 7GB。


.NET 9 的 Native AOT(Ahead-of-Time Compilation)是微软在.NET 9版本中重点发展的一项技术,旨在提升应用程序的性能。Native AOT 技术可以将.NET 代码预先编译为本地代码,从而实现更快的启动时间和更高的执行效率。

在.NET 9中,微软已经将Native AOT作为提升性能的关键点之一[2]。此外,微软还宣布了对通用Windows平台(UWP)的初步支持,允许开发者使用.NET 9和Native AOT技术来现代化改造现有的UWP应用。这一举措为UWP开发者提供了一条升级路径,使他们能够利用最新的.NET和Native AOT技术来改进其应用程序。 .NET 9的Native AOT不仅限于UWP平台,它还支持老旧的Windows 7和XP环境,这标志着AOT技术在兼容性方面的突破。然而,对于Android平台的Native AOT支持,目前尚未完成,尤其是JNI(Java Native Interface)支持,这被认为是一个较大的功能需求,还有WPF/Winform 的Native AOT支持也需要在.NET 10 才能够完成。

.NET 的Native AOT技术通过在编译阶段对代码进行优化,使得生成的可执行文件更小且启动速度更快。这一突破性功能不仅实现了对老旧Windows 7和Windows XP环境的支持,还为性能要求高且依赖旧版系统的开发者提供了新的可能性。具体来说,.NET 9版本中,为了确保向下兼容性,X86架构下的AOT(Ahead-of-Time)编译器的支持扩展,.NET 9采用了精心设计的编译策略,确保了对Win7及XP API的兼容性,使代码能够无缝运行,允许开发人员将应用程序在编译阶段就优化为能够在老旧的Windows系统上运行。LoongArch架构和Risc-V架构下的AOT 编译器支持,社区也在继续完善之中。

在.NET 9中,对Native AOT(按需编译)支持和JNI(Java Native Interface)的支持有以下具体进展:

  • 在.NET 9中,引入了两个新的属性,允许开发者设计功能开关。这些功能开关可以在.NET库(以及你自己)中使用来切换某些功能区域。如果一个功能不被支持,在裁剪或使用Native AOT进行编译时,将移除那些不受支持且不必要的功能,从而减小应用程序的大小。
  • 在.NET MAUI的测试中,通过调用JNI来获取Java数组元素的性能比使用string.Split和新的Span方法更差。这表明开发者正在考虑如何在未来版本中优化这一过程。
  • .NET 9在Android平台上对Native AOT的支持主要体现在通过新属性实现的功能开关,以及通过Native AOT减少应用大小的能力。

对于开发者而言,学习和采用.NET 9的Native AOT技术需要具备以下前置知识或技能:

  1. 对.NET平台的理解:首先,开发者需要对.NET平台有基本的了解,包括其架构、运行时环境以及如何在不同平台上部署应用。这有助于理解Native AOT技术如何与现有.NET生态系统集成。

  2. 熟悉C#或F#编程语言:由于.NET 9支持通过C#或F#进行开发,因此掌握这些编程语言是必要的。此外,了解这些语言的高级特性将有助于更有效地利用Native AOT带来的性能优势。

  3. 了解编译器原理:Native AOT(Native Application Optimized Translation)是一种预编译技术,它允许开发者直接生成机器码而不是依赖JIT(即时编译)。因此,对编译器的工作原理有一定的了解可以帮助开发者更好地理解和使用Native AOT技术[3]。

  4. 性能优化经验:由于Native AOT旨在提供可预测的性能并减少资源消耗,因此具备一定的性能优化经验是有益的。这包括对内存管理、代码优化等方面的深入了解。

  5. 云原生和微服务架构知识:虽然不是必须的,但了解云原生应用和微服务架构的相关知识可以增强开发者在使用.NET 9时构建高效、可扩展的应用的能力。这是因为.NET 9特别强调了在这些架构中的性能表现,参见.NET 9 RC1发布[4]。

随着 .NET 的不断发展,我们可以期待更多的库和框架支持Native AOT,这使其成为希望优化其应用程序的开发人员更具吸引力的选择。那么为什么不试一试,看看你能在多大程度上提升你的应用的性能呢?

相关链接:

From:https://www.cnblogs.com/shanyou/p/18415013
本文地址: http://shuzixingkong.net/article/2035
0评论
提交 加载更多评论
其他文章 全网最适合入门的面向对象编程教程:49 Python函数方法与接口-函数与方法的区别和lamda匿名函数
在 Python 中,函数和方法都是代码的基本单元,用于封装和执行特定的任务。它们之间有一些重要的区别,而 lambda 匿名函数则是 Python 提供的一种简洁定义小型函数的方法。
全网最适合入门的面向对象编程教程:49 Python函数方法与接口-函数与方法的区别和lamda匿名函数 全网最适合入门的面向对象编程教程:49 Python函数方法与接口-函数与方法的区别和lamda匿名函数 全网最适合入门的面向对象编程教程:49 Python函数方法与接口-函数与方法的区别和lamda匿名函数
痞子衡嵌入式:JLink命令行以及JFlash对于下载算法的作用地址范围认定
大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家分享的是JLink命令行以及JFlash对于下载算法的作用地址范围认定。 最近痞子衡在给一个 RT1170 客户定制一个 Infineon MirrorBit 类型 64MB Flash 的 SEGGER 下载算法,做完之后在 JFlash 下
痞子衡嵌入式:JLink命令行以及JFlash对于下载算法的作用地址范围认定 痞子衡嵌入式:JLink命令行以及JFlash对于下载算法的作用地址范围认定 痞子衡嵌入式:JLink命令行以及JFlash对于下载算法的作用地址范围认定
CMake构建学习笔记16-使用VS进行CMake项目的开发
详细介绍了通过Visual Studio 2019 这款IDE进行CMake项目开发过程,能够极大增加C/C++程序的开发效率。
CMake构建学习笔记16-使用VS进行CMake项目的开发 CMake构建学习笔记16-使用VS进行CMake项目的开发 CMake构建学习笔记16-使用VS进行CMake项目的开发
分析负数取模与取余的规则
目录负数"取模"基本概念修正定义取整规则决定商的值取模和取余不一样. 负数"取模" 基本概念 如果a和d是两个自然数,d非零,可以证明存在两个唯一的整数 q 和 r,满足 a = q*d + r,且0 <= r < d。其中,q 被称为商,r 被称
分析负数取模与取余的规则 分析负数取模与取余的规则 分析负数取模与取余的规则
深度!程序员生涯的垃圾时间(上)
深度好文!程序员的垃圾时间! 垃圾时间(Garbage time)是体育赛事中的术语,指一场比赛中双方分差过大,胜负已定。此时,比赛剩余的时间不再对最终结果产生决定性影响,剩下的时间就被称为垃圾时间。将这个词用在浩浩荡荡的技术革命、汹涌向前的历史车轮上,再合适不过。时代的必然,是个人无法违背的规律。
Nuxt Kit 组件管理:注册与自动导入
title: Nuxt Kit 组件管理:注册与自动导入 date: 2024/9/15 updated: 2024/9/15 author: cmdragon excerpt: Nuxt Kit 为组件的注册和导入提供了灵活高效的解决方案。无论你是要批量导入组件,还是单独处理特定组件,这些工具都能
Nuxt Kit 组件管理:注册与自动导入 Nuxt Kit 组件管理:注册与自动导入
1Panel:一个现代化、开源的 Linux 服务器运维管理面板
前言 之前有小伙伴问:Linux 服务器运维管理除了宝塔,还有其他值得推荐的管理软件吗?,今天大姚给大家分享一个现代化、开源的 Linux 服务器运维管理面板:1Panel。 项目介绍 1Panel是新一代的 Linux 服务器运维管理面板,旨在通过现代化的 Web 界面帮助用户轻松管理 Linux
1Panel:一个现代化、开源的 Linux 服务器运维管理面板 1Panel:一个现代化、开源的 Linux 服务器运维管理面板 1Panel:一个现代化、开源的 Linux 服务器运维管理面板
二叉树的 Morris 中序遍历——O(1)空间复杂度
回顾 问题陈述: 给定一棵二叉树,实现中序遍历并返回包含其中序序列的数组 例如给定下列二叉树: 我们按照左、根、右的顺序递归遍历二叉树,得到以下遍历: 最终中序遍历结果可以输出为: [3, 1, 9, 2, 4, 7, 5, 8, 6] Morris trick Morris 中序遍历是一种树遍历算
二叉树的 Morris 中序遍历——O(1)空间复杂度 二叉树的 Morris 中序遍历——O(1)空间复杂度 二叉树的 Morris 中序遍历——O(1)空间复杂度