[.NET大牛之路 005] .NET 的执行模型

.NET大牛之路 • 王亮@精致码农 • 2021.07.06

前面我们介绍 .NET 历史时讲过,微软基于 .NET Framework 重新设计并创造了跨平台的 .NET Core,目前已经发展到 .NET 5 版本,它的性能较之前的 .NET Framework 有巨大的提升。而 .NET Framework 产品线也被宣告终止(微软仍会继续维护,只是不会再发布新版本),它的最后个版本 .NET Framework 4.8 成为了绝唱。

.NET Framework 终将成为历史,我们要把思想从 .NET Framework 跳到 .NET Core/.NET 5+,首先要弄明白它们的执行模型和底层架构发生了什么变化。

注:为了简单起见,下文所说的 .NET Core 包含 .NET Core 和 .NET 5+。

我们先从一个高的角度来理解一下 .NET Core 执行模型的全貌,后面章节再从低的角度逐个拆开讲解各个模块。

.NET Core 的执行模型有两种,一种是基于 CoreCLR 运行时,这种和 .NET Framework 的执行模型几乎一样;另一种是基于 Native AOT 本地运行时,这是 .NET Core 新增的一种执行模型。

基于 CoreCLR

CoreCLR 和原来 .NET Framework 的 CLR(Common Language Runtime,公共语言运行时)几乎是一样的,只是 CoreCLR 去除了特定于 Windows 操作系统的部分,实现了跨平台。所以除了 CLR 运行时有些不同之外,它们的执行模型是一样的。

注意,平时我们会把 CoreCLR 习惯性地简称为 CLR,在 .NET Core 语境中,CLR 指的就是 CoreCLR。

基于 CoreCLR 的执行模型用简单流程图表示如下:

[.NET大牛之路 005] .NET 的执行模型

源代码经过编译器编译,生成程序集,运行的时候,再由 CLR 针对不同的操作系统和 CUP 架构(如 x86、x64 或 ARM)把程序集编译成本地代码(Native Code),本地代码可由操作系统直接运行。

注:在 .NET 中,本地代码就是机器码(Machine Code),只是叫法不同。它是处理器能够理解并直接执行的字节码指令。所有其他代码必须翻译或转换为机器码才能在计算机上运行。

基于 Native AOT

.NET Core 基于 CoreCLR 提炼出了一个精简版的本地运行时,移除了 JIT 编译器,保留了垃圾回收器、内存管理等模块。这个本地运行时之前的代号叫 CoreRT ,现在叫 Native AOT

Native AOT 运行时提供了一套 AOT(Ahead Of Time) 提前编译机制,它使用的是新一代的 RyuJIT 编译器,可以将 .NET Core 程序编译成本地代码(机器码),可在宿主机器直接运行,不需要提前安装 .NET Core 运行时。

基于 Native AOT 运行时的执行模型用简单流程图表示如下:

[.NET大牛之路 005] .NET 的执行模型

源代码经过编译器编译,直接生成本地代码,发布时将本地代码和本地运行时一起打包为单个可执行文件,可直接在操作系统上运行。

要使用本地运行时,在 VS 中发布时请选择 Self-Contained 模式,同时需指定目标平台及 CPU 架构(如win-x64linux-x65等)。由于打包的文件包含本地运行时,所以它要比基于 CoreCLR 发布的文件要大几十兆。

使用 Native AOT 本地运行时有两大好处:一是发布时只有一个文件,已经包含本地运行时,不需要提前安装运行时环境,可直接在宿主机上运行;二是启动时本身就是机器吗,不要经过 JIT 编译器编译,启动效率更高。

小结

.NET Core 基于 CoreCLR 的执行模型和原来 .NET Framework 的执行模型是一样的,没有发生大的变化。另外,.NET Core 新增了一种基于 Native AOT 本地运行时的执行模型,它使用了 AOT 编译机制,可直接把 .NET Core 程序编译成机器码。

希望大家根据文中的流程图理解 .NET Core 两个执行模型的全貌,并牢记。这有助于我们理解 .NET 程序的运行原理,也是面试的高频话题。关于执行模型中的主要核心模块(编译器、程序集和运行时),后面的章节再单独详细讲解。

上一篇:005.列表


下一篇:备忘录(005) - Centos8安装配置MySQL8.0.26